Documente Academic
Documente Profesional
Documente Cultură
VE
TThe
h e LLeading
e a d i n g IIndependent
ndependent M
Magazine
a g a z i n e ffor
or M
Microsoft
icrosoft D
Developers
evelopers
Volume 5 / Issue 2
CoDe_FocusLive.indd 1
CoDe_FocusLive.indd 2
EPS
Can Help!
EPS Software provides:
Application
Development
Prototyping Services
Situation Assessment
Project Management
Mentoring
Training
Contact us at:
info@eps-software.com
866-529-3682
www.eps-software.com
CoDe_FocusLive.indd 3
TABLE OF CONTENTS
Features
6 Welcome to the Windows Live Platform
CoDe Focus Magazine
Angus Logan
Rob Blackwell
Sctt Lovegrove
John OBrien
Jason Kelly
Vaishali De
Bronwen Zande
Vikas Ahuja
Jon Arking
Departments
5 CoDe Compilers
37 Advertisers Index
US subscriptions are US $29.99 for one year. Subscriptions outside the US pay US $44.99. Payments should be made in US dollars drawn on a US
bank. American Express, MasterCard, Visa, and Discover credit cards are accepted. Bill me option is available only for US subscriptions. Back issues
are available. For subscription information, email subscriptions@code-magazine.com or contact customer service at 832-717-4445 ext 10.
Subscribe online at www.code-magazine.com
CoDe Component Developer Magazine (ISSN # 1547-5166) is published bimonthly by EPS Software Corporation, 6605 Cypresswood Drive., Suite
300, Spring, TX 77379. POSTMASTER: Send address changes to CoDe Component Developer Magazine, 6605 Cypresswood Drive., Suite 300,
Spring, TX 77379.
Table of Contents
CoDe_FocusLive.indd 4
www.code-magazine.com
developer
CODE COMPILERS
component
March 2008
magazine
Volume 5 Issue 2
Group Publisher
Markus Egger
Associate Publisher
Rick Strahl
Managing Editor
Ellen Whitney
Content Editor
H. Kevin Fansler
Writers In This Issue
Vikas Ahuja
Jon Arking
Paul Birkbeck
Rob Blackwell
Vaishali De
Jason Kelly
Angus Logan
Michle Leroux Bustamante
Sctt Lovegrove John OBrien
Dr. Neil Roodyn Bronwen Zande
Technical Reviewers
H. Kevin Fansler
Angus Logan
Ellen Whitney
Art & Layout
King Laurin GmbH
info@raffeiner.bz.it
Production
Franz Wimmer
King Laurin GmbH
39057 St. Michael/ Eppan, Italy
Printing
Fry Communications, Inc.
800 West Church Rd.
Mechanicsburg, PA 17055
Advertising Sales
Vice President, Sales and Marketing
Tom Buckley
832-717-4445 ext 34
tbuckley@code-magazine.com
Sales Managers
Erna Egger
+43 (664) 151 0861
erna@code-magazine.com
Tammy Ferguson
832-717-4445 ext 26
tammy@code-magazine.com
Circulation & Distribution
General Circulation: EPS Software Corp.
Newsstand: Ingram Periodicals, Inc.
Media Solutions
Worldwide Media
Subscriptions
Subscriptions Manager
Cleo Gaither
832-717-4445 ext 10
subscriptions@code-magazine.com
US subscriptions are US $29.99 for one year.
Subscriptions outside the US are US $44.99.
Payments should be made in US dollars drawn
on a US bank. American Express, MasterCard,
Visa, and Discover credit cards accepted. Bill
me option is available only for US subscriptions.
Back issues are available. For subscription
information, email subscriptions@code-maga-
zine.com
or contact customer service at 832-717-4445 ext 10.
Subscribe online at
www.code-magazine.com
CoDe Component Developer Magazine
EPS Software Corporation / Publishing Division
6605 Cypresswood Drive, Ste 300,
Spring, Texas 77379
Phone: 832-717-4445
Fax:
832-717-4460
CoDe_FocusLive.indd 5
Welcome to the
Windows Live Platform
CoDe Focus Magazine
Angus Logan
Senior Technical Product
Manager
alogan@microsoft.com
Angus Logan is a Senior
Technical Product Manager
in the Windows Live Platform
team in Redmond.
Anguss team is responsible for
all technical marketing content
ranging from conference
presentations (MIX, TechEd)
to online samples (Windows
Live Quick Apps).
Prior to being on the Windows
Live Platform team, Angus was
a Portals Technology Specialist
with Microsoft Australia.
Prior to that, Angus worked
for several Microsoft partners,
was an MVP, and co-authored
a book on Microsoft Content
Management Server.
You can read Anguss blog
at http://blogs.msdn.com/
angus_logan/
Fast Facts
The Windows Live Platform
Quick Applications are
segment-focused, open
source demos.
They range from
Tafiti Search Visualization
(Silverlight front end over
Live Search API) to Adventure
Works Resorts
(a fictitious social network).
For more information see
http://dev.live.com/quickapps
More Resources
This issue of CoDe Focus
is a great place to start,
but here are some other
Web sites you might want
to check out:
www.ViaWindowsLive.com
CoDe_FocusLive.indd 6
www.code-magazine.com
Introduction to Microsofts
Windows Live Platform
From the consumer products associated with the MSN Butterfly,
the Windows Live Platform has steadily grown and evolved.
In this article you will discover some of the history behind the Windows Live
Platform and explore where it is heading now and might be destined to go in the
future. This article will explore the opportunities for you as a developer in this
brave (nearly) new world.
Dr. Neil
Neil@Roodyn.com
www.code-magazine.com
CoDe_FocusLive.indd 7
http://ViaWindowsLive.com,
a Web site to help developers
build on Windows Live
services.
The new
cloud services are changing the
way that developers
can write code online.
The Sunshine Through the Clouds
You are probably wondering what impact this has on
you as a developer. You might be questioning the value of accessing these in the cloud services. In many
ways this is a similar situation to when Windows
(and OS2) started shipping on PCs. Many developers
didnt really see the point in getting involved in all that
messy point-and-click mouse movement; it turned out
to be the way that every PC developer would end up
working. In the same way that Windows changed
the way developers wrote software for PCs, the new
cloud services are changing the way that developers
can write code for their online applications.
The opportunities to place your application in the
hands of the millions of users that already have a
commitment to the Windows Live products are numerous and potentially very rewarding. To make
your life more interesting, the world of online users
that utilize the Windows Live products is incredibly
diverse and segmented. If you want to create a Web
site for rock climbers that live in Manhattan you
can be fairly certain that a large percentage of them
will have a Live ID (the standard Windows Live
authentication) to log in to a Hotmail, Messenger,
or Spaces account. Letting a user log in to your site
with their existing credentials does several things:
The user doesnt have to remember another
user name and password for your site, they use
something they are already familiar with.
Your site can potentially get access to the users
Windows Live connections, often that means
their social network, but it could be as simple
as providing them a gadget for their Windows
Live Spaces account.
Your new Web site aligns itself with the powerful Microsoft Windows Live brand by leveraging their services.
Your site can utilize Microsofts online infrastructure to host content, manage domains,
stream media, and maintain relationships between users.
CoDe_FocusLive.indd 8
Online Applications
Before you start thinking about how to build these
new Internet applications, it is worth taking a step
back and thinking of some of the concepts behind
an online application. If your application is no longer simply serving markup files to be rendered in a
browser, there are some considerations to be taken
on the architecture of your product.
In reality the
Web sites are becoming
a fuzzy mix of old style
HTML brochures
and rich components.
www.code-magazine.com
www.code-magazine.com
CoDe_FocusLive.indd 9
Building an application
to service millions (or billions)
of transactions a day seems like a
daunting task but the
architecture is well defined.
one of these applications today. RSS Readers, email Clients, iTunes, and Live Writer are all great
examples of smart client applications that provide
richer experiences for users than their browserbased counterparts.
Consider this as you start building your applications to take advantage of Windows Live services.
Right now you might be constrained to the browser, but the future of online services will be defined
by applications that disregard the browser and
build on the power of the computer.
Neil Roodyn
10
CoDe_FocusLive.indd 10
www.code-magazine.com
www.code-magazine.com
CoDe_FocusLive.indd 11
Michle Leroux
Bustamante
mlb@idesign.net
Michle Leroux Bustamante is
Chief Architect of IDesign Inc.,
Microsoft Regional Director
for San Diego, and a Microsoft
MVP for Connected Systems.
At IDesign Michle provides
training, mentoring and highend architecture consulting
services focusing on scalable
and secure architecture
design for .NET, Web services,
interoperability, federated
security scenarios, CardSpace,
and globalization architecture.
Michle participates in
Software Design Reviews
for products in the Microsoft
roadmap, including WCF,
CardSpace, and other securityfocused products. During
the Beta 1 phase Michle
participated in prototyping
elements of the CardSpace
technology for the product
team. She is a member of the
International .NET Speakers
Association (INETA), a
frequent conference presenter,
conference chair for SD West,
and is frequently published
in several major technology
journals. Michle is also on
the board of directors for IASA
(International Association of
Software Architects) and a
Program Advisor to UCSD
Extension. Her latest book
is Learning WCF, OReilly
2007see her book blog here:
www.thatindigogirl.com. Reach
her at mlb@idesign.net or visit
www.idesign.net and her main
blog at www.dasblonde.net.
Live from the Web! Bring the Windows Live Messenger Experience to Your Web Applications
11
While the IM control and presence API are the easiest to implement and do not require development
experience, the Messenger Library provides a rich
set of features that require developers to provide the
UI and programmatically control all interactions
with Windows Live Messenger. Each has their place
in the community depending on the goals of your
Web application. This article will explain when and
how to incorporate the IM control, presence API,
and Messenger Library in your Web applications
while discussing common scenarios where each are
distinctly useful.
Paul Birkbeck
paul.birkbeck@multiplied.com
Paul Birkbeck is Director of
Software Development and
Lead Architect at Multiplied
Media Corporation
(www.multiplied.com).
At Multiplied Media,
Paul leads the development
effort for their flagship product,
Poynt
(www.mypoynt.com)a
multimedia local search service
that leverages Windows Live
Messenger as its primary
delivery channel. Pauls
technology expertise lies
in building large enterprise
systems for the past 15 years,
focusing primarily on Microsoft
technologies. His current focus
is in the Windows Live product
suite including Messenger,
Virtual Earth, and Search. Paul
has his MCSD.NET and he
recently started a new .NET
User Group in Barrie, Ontario,
Canada. Reach him at
paul.birkbeck@multiplied.com
Figure 1:
From the Create
HTML page in
Web Settings you
can configure
the IM controls
appearance
and copy the
resulting HTML
to any Web page.
The Windows
Live Messenger
IM Control lets
you share your
presence as a
status icon, a
button, or by
presenting an IM
window.
12
Live from the Web! Bring the Windows Live Messenger Experience to Your Web Applications
CoDe_FocusLive.indd 12
www.code-magazine.com
Live Team
Figure 2: On the Home page in Web Settings you must first allow Web sites access to your messenger presence before the
IM control can be useful.
gin a chat session. If you are online, the IM window
is enabled so that visitors can send messages, otherwise it is disabled. To set up, you will generate the appropriate HTML for the IM control according to the
choice of online presence you prefer to share within
your Web application.
The IM control is supported by IE 6, IE 7, and Firefox 2.0 on Windows or Mac OS. Aside from deciding
how you would like to share your online presence
with visitors, you can also personalize the controls
appearance and culture settings. When you generate
the HTML for the control, you can choose a template to initialize font and color properties to match
your Web applications appearance. The control is
also localized to 32 languages, so by simply setting
a property you can adjust the language presented to
your visitors. This article will talk about the control
HTML and related properties next.
Steve Gordon
Lead Software Design
Engineer
Steve's team is on point to
expose the rich capabilities
of Windows Live Messenger
and Contacts to the full range
of Web developers. Using
controls that can be quickly
embedded into existing Web
sites or APIs that facilitate rich
IM and presence-enabled Web
applications, developers can
build powerful and compelling
experiences for their users with
minimal effort.
Steve has been a member
of the Messenger team for
three years. During his tenure,
he has had the opportunity
to implement a range of
functionality within the service;
however, he is most excited
about enabling developers to
leverage the platform to create
applications that delight users.
Listing 1: The resulting HTML generated for the status icon, button, and IM window, with no themes applied.
<!-- HTML for status icon -->
msgr:altBackColor="#FFFFFF"
msgr:foreColor="#424542"
msgr:conversationUrl="http://settings.messenger.live.com/
Conversation/IMMe.aspx?invitee=[unique id]@apps.messenger.live.
com&mkt=en-US"></div>
<script type="text/javascript"
src="http://messenger.services.live.com/users/
[unique id]@apps.messenger.live.com/presence?mkt=enUS&cb=Microsoft_Live_Messenger_PresenceButton_onPresence"></
script>
www.code-magazine.com
CoDe_FocusLive.indd 13
<iframe
src="http://settings.messenger.live.com/Conversation/IMMe.aspx?
invitee=[unique id]@apps.messenger.live.com&mkt=en-US"
width="300" height="300" style="border: solid 1px black; width:
300px; height: 300px;" frameborder="0"></iframe>
Live from the Web! Bring the Windows Live Messenger Experience to Your Web Applications
13
Figure 3: To start a new conversation via the IM windowidentify yourself, retype the CAPTCHA text, and send your message.
14
Live from the Web! Bring the Windows Live Messenger Experience to Your Web Applications
CoDe_FocusLive.indd 14
headerForeColor=0066A7&headerBackColor=8EBBD8&
menuForeColor=333333&menuBackColor=FFFFFF&
chatForeColor=333333&chatBackColor=FFFFFF&
chatDisabledColor=F6F6F6&chatErrorColor=760502&
chatLabelColor=6E6C6C"
width="300" height="300" style="border: solid 1px
black; width:300px; height:300px;"
frameborder="0"></iframe>
www.code-magazine.com
IM Control
IM Client
that the control can gain access to your online presence and do things like display your status icon and
name. You can do the same for users that visit your
Web application by inviting them to share their online presence via the Web sign-up URL. This makes
it possible to identify visitors by their messenger ID
and use that to show their online presence information for a personalized experience.
The following hyperlink will send the user to the Windows Live ID sign-up page (websignup.aspx) to sign
in, supplying a return URL (default.aspx) for the host
application, and a privacy policy URL (privacypolicy.
aspx) so that users can verify trust:
<asp:HyperLink ID="lnkSharePresence"
runat="server" NavigateUrl=
"http://settings.messenger.live.com/
applications/websignup.aspx?
returnurl=http:///default.aspx&
privacyurl=http:///privacypolicy.aspx">
Share Your IM Presence</asp:HyperLink>
[unique id]@anonymous.messenger.live.com
www.code-magazine.com
CoDe_FocusLive.indd 15
Figure 5: During the Windows Live Web sign-in process, users are asked to enable their presence
and to confirm that they will share their messenger ID with the site they are visiting.
Live from the Web! Bring the Windows Live Messenger Experience to Your Web Applications
15
The following code illustrates how to gather the query string parameters and process the various possible
responses:
You can pass the messenger ID for any user, including one retrieved from a call to the Web sign-up
page discussed earlier. The messenger ID is in the
form:
if (!this.IsPostBack)
{
string result = Request.QueryString["result"];
string id = Request.QueryString["id"];
if (!String.IsNullOrEmpty(result))
{
if ((result == "Accepted") && (id != null))
this.lblName.Text = "Presence ID: " + id;
else if (result == "Declined")
this.lblName.Text = "Presence unavailable.";
else if (result == "NoPrivacyUrl")
this.lblName.Text = "No privacy Url.";
}
}
16
Live from the Web! Bring the Windows Live Messenger Experience to Your Web Applications
CoDe_FocusLive.indd 16
http://messenger.services.live.com/users/
[messenger id]/[resource]/[?queryparameters]
[unique id]@apps.messenger.live.com
www.code-magazine.com
{
"status": "[messenger status]",
"icon": {
"height": 16,
"url":
"http://settings.messenger.live.com/static/w13r2
/Conversation/img/[status icon lename].gif",
"width": 16
},
"statusText": "[localized messenger status]",
"id": "[messenger id]@apps.messenger.live.com",
"displayName": "[messenger display name]"
}
www.code-magazine.com
CoDe_FocusLive.indd 17
Live from the Web! Bring the Windows Live Messenger Experience to Your Web Applications
17
language="javascript">
</script>
<script
src="App_Scripts\MyMessengerScriptLibrary.js"
type="text/javascript" language="javascript">
</script>
The Importance of
Privacy Policies
As they say: with great power
also comes great responsibility.
The privacy policy of the
Windows Live Messenger
Library explicitly forbids the
use of the information available
through the SDK for SPAM
over IM (SPIM). Certainly any
sites that misuse this power
will swiftly be blacklisted or
become social outcasts.
Thus Web applications that
leverage the Windows Live
Messenger Library must
provide very clear privacy
policies and use ethical
business practices as they
interact with the information
available to them.
<div id="divSignIn">
</div>
</body>
As for the coding experience, the previous code snippet for the JavaScript function named authenticateUser() would look like this in the Script# library:
namespace MyMessengerScriptLibrary
{
public class Authentication
{
public static void authenticateUser()
{
SignInControl signinControl = new
SignInControl("divSignIn",
"http://.../PrivacyPolicy.htm",
"http://.../Channel.htm", "");
function AuthenticateUser()
{
signinControl = new
Microsoft.Live.Messenger.UI.SignInControl(
'divSignIn',
'http:///PrivacyPolicy.aspx',
'http:///Channel.aspx', '');
}
18
Live from the Web! Bring the Windows Live Messenger Experience to Your Web Applications
CoDe_FocusLive.indd 18
}
}
}
NOTE: Keep in mind that at the time of this writing, the Script# compiler changes Pascal case
function names to Camel case names.
In this article, all code to work with the Messenger
Library is written in a Script# library, and thus will
be illustrated in C# using the steps just described.
The compiled JavaScript is ultimately what Web
pages invoke at run timeand given the richness
of the Messenger Library, using Script# is the key
to developer productivity. The Windows Live Messenger Library is a substantive library with over 70
classes for building Messenger-enabled applications.
The remainder of this article will discuss three key
scenarios related to working with users and sign in,
contacts, and conversations.
www.code-magazine.com
About Script#
which handles authentication of users against the
Windows Live ID domain. Once it authenticates the
user, you can gain access to the user identity and interact with the sign-in and sign-out process for that
user. In addition, through the user identity you can access many other details related to the users Windows
Live ID accountwhich makes it possible to replicate
the messenger client in a customized Web interface.
To add Windows Live ID sign-in functionality to a
page, create an instance of the SignInControl located
in the Microsoft.Live.Messenger.UI namespace of the
Messenger Library. The control constructor has four
parameters:
controlId: The name of the <div> on the page
where the control should be rendered.
privacyStatementUrl: The URL of the Web applications privacy policy, explaining how the
application will use the users account details.
channelUrl: A URL for a page containing
JavaScript for safe cross-site scripting. See following reference for more details on how this
secures communication between third-party
sites and the Windows Live ID domain: http://
msdn2.microsoft.com/en-us/library/bb735305.aspx.
market: An optional culture code specifying
which culture the control should use to display
text.
tication (see Figure 7). If they choose to be automatically signed in, Windows Live ID Web Authentication
(http://dev.live.com/liveid) is used to authenticate the
user with the Windows Live ID cookie stored on the
machine.
NOTE: Windows Live ID Web Authentication
is a free product you can also employ in your
Web applications to authenticate users to your site
using their Windows Live ID accounts, instead of
employing a custom authentication mechanism.
While the SignInControl does provide core functionality for authentication, to fully leverage the Messenger Library you will have to write code to interact
with the authentication process. Listing 3 includes
the code necessary to create the SignInControl, interact with the authentication process, access the authenticated users identity, and, post sign in, access
www.code-magazine.com
CoDe_FocusLive.indd 19
Figure 7: Users have an opportunity to configure their sign-in settings with Windows Live ID. The
Web site clearly states what the requesting host application will have access to and provides a link
to the privacy policy specified in the SignInControl constructor.
Live from the Web! Bring the Windows Live Messenger Experience to Your Web Applications
19
Function Name
Description
authenticateUser()
Creates the SignInControl and hooks its AuthenticationCompleted event so that you can
retrieve the user identity during sign in.
signinControl_
AuthenticationCompleted()
Creates an instance of the User from the identity passed in; hooks the SignInCompleted
event so that you can verify the status of the sign in; and invokes the SignIn() function to
complete the sign-in process.
userAccount_SignInCompleted()
Verifies the success or failure of the sign-in process and, if successful, displays the user
accounts details.
displayAccountDetails()
Accesses the user accounts details through the User object model.
Table 1: The functions used to handle SignInControl authentication and access to user account details.
Category
Description
Functions to sign in or sign out and events to interact with the process providing access to the user identity.
Account settings
Properties to interact with account settings related to privacy mode, the existence of a mailbox or special
features such as mobile messaging, and other settings such as the ability to update the display name of the
account.
Account details
Properties to interact with address settings, address capabilities, online status, presence details including
display name and IM address, and the users identity.
Contacts
Access to the users contacts collection, the ability to add new contacts and access contact details, access to
contact groups, and functionality to send messages to contacts.
Conversations
Functionality supporting creating new conversations with contacts, sending and receiving messages, and
interaction with message generation and formatting.
Table 2: A high-level look at the powerful features available through the User type in the Windows Live Messenger Library.
20
Live from the Web! Bring the Windows Live Messenger Experience to Your Web Applications
CoDe_FocusLive.indd 20
www.code-magazine.com
Each ContactCollection contains a list of Contact instances that contain details about each contact. This
information is useful for presenting the signed-in
users contacts in the UI for them to interact with.
Listing 4 shows you how to present a list of contacts to the user after they sign in, organizing the
list by group. In the SignInCompleted event, if sign
in is successful, listContacts() is called to traverse
the contacts within each group. The contact collection for the user and the list of contact IMAddress
instances are saved for later use at the client. Then,
the contact collection for each group is traversed
building an <a> element showing the address of the
contact:
<a href='javascript:MyMessengerScriptLibrary.
ContactsByGroup.showContactDetails([contactIndex])
'>[contactAddress]</a>
Presence.PersonalMessage,
Presence.IMAddress.
Address, Presence.Status, IsAllowed, and IsBlocked.
You can use the collection to produce a contact list
for the signed-in user to communicate with directly
from the browser. You can filter this list to organize
by groups, include only unblocked contacts, or even
to produce UI to toggle contact properties, such as
unblocking or blocking contacts using the Allow()
and Block() functions (respectively) exposed by the
Contact class. You can also provide messaging features for the signed-in user so they can exchange
messages with their online contacts. Beyond messenger-like functionality, your Web applications can
also provide other unique ways for signed-in users to
interact with their contact list, such as inviting them
to join the application or sending them a link to the
content they are browsing. In this respect, youve
created an instant social network for the user within
the context of your Web application.
Listing 3: C# code illustrating how to create the SignInControl, handle authentication, and access user account details.
{
namespace MyMessengerScriptLibrary
{
public class AccountDetails
{
private static SignInControl signinControl;
private static User userAccount;
sb.Append("DisplayPictureUrl: ");
sb.Append(userAccount.Presence.DisplayPictureUrl.ToString());
sb.Append("<br/>");
sb.Append("PersonalMessage: ");
sb.Append(userAccount.Address.Presence.PersonalMessage);
sb.Append("<br/>");
sb.Append("Address: ");
sb.Append(userAccount.Address.Address);
sb.Append("<br/>");
sb.Append("LiveId: ");
sb.Append(userAccount.Identity.LiveId);
sb.Append("<br/>");
sb.Append("Status: ");
sb.Append(userAccount.Address.Presence.Status.ToString());
sb.Append("<br/>");
Document.GetElementById("divWelcome").InnerHTML =
sb.ToString();
}
}
}
www.code-magazine.com
CoDe_FocusLive.indd 21
Live from the Web! Bring the Windows Live Messenger Experience to Your Web Applications
21
The message is sent to the Windows Live account associated with the IM Addressand if they are signed
in to the messenger client, a new conversation window will appear with the message. If you handle the
SendMessageFailedEventHandler, you will be informed of any failed deliveries so you can present this
information to the user.
SendMessage() supports three different types of messagesTextMessage, NudgeMessage, and ApplicationMessagethe latter of which provides an extensibility
point for custom messages. You can send a nudge to
the participants of a conversation as follows:
conv.SendMessage(new NudgeMessage(), null);
Messages sent from a messenger-enabled Web application will be sent to the messenger application
where the user is signed in. They, in turn, will likely
send messages back. In order to retrieve messages
sent by conversation participants you must hook the
MessageReceivedEventHandler of the Conversation
class after creating the conversation:
Conversation conv = userAccount.Conversations.
Create(contact.CurrentAddress);
conv.MessageReceived += new
MessageReceivedEventHandler(conv_MessageReceived);
22
Live from the Web! Bring the Windows Live Messenger Experience to Your Web Applications
CoDe_FocusLive.indd 22
Of course participants using the messenger client application may also invite additional participants. If
you are presenting a list of participants to the user,
youll need to know when they add or remove new
participants. The Roster property of the conversation
instance tracks these changes. You can handle the
CollectionChanged event of the Roster as follows:
conv.Roster.CollectionChanged += new
NotifyCollectionChangedEventHandler(
Roster_CollectionChanged);
Conclusion
Unlike the simplicity of the Windows Live Messenger
IM Control and Windows Live Messenger Presence
API, the Windows Live Messenger Library provides
www.code-magazine.com
sb.Append("PersonalMessage: ");
sb.Append(address.Presence.PersonalMessage);
sb.Append("<br/>");
sb.Append("Address: ");
sb.Append(address.Presence.IMAddress.Address);
sb.Append("<br/>");
contactList = userAccount.Contacts;
addressList = new IMAddress[userAccount.Contacts.Count];
foreach (Group g in userAccount.Groups)
{
sb.Append("<h1>");
sb.Append(g.Name);
sb.Append("</h1>");
sb.Append("Status: ");
sb.Append(address.Presence.Status.ToString());
sb.Append("<br/>");
sb.Append("<b>Contact</b><br/>");
sb.Append("IsAllowed: ");
sb.Append(c.IsAllowed.ToString());
sb.Append("<br/>");
sb.Append("IsBlocked: ");
sb.Append(c.IsBlocked.ToString());
sb.Append("<br/>");
sb.Append("<a href='javascript:MyMessengerScriptLibrary.ContactsByGroup.
showContactDetails(" + index + ")'>" +
c.CurrentAddress.Address + "</a><br />");
index++;
}
Document.GetElementById("divSelectedContact").InnerHTML +=
sb.ToString();
}
}
Document.GetElementById("divContactList").InnerHTML +=
sb.ToString();
}
www.code-magazine.com
CoDe_FocusLive.indd 23
Live from the Web! Bring the Windows Live Messenger Experience to Your Web Applications
23
John OBrien
Now in its sixth major release, Virtual Earth offers an entire world
of opportunities for innovative Web-based mapping.
Microsofts premier Web-based mapping solution has undergone upgrades to
its user interface, compatibility, and functionality making it an ideal time to
get started with the platform or upgrade your existing application. Lets explore
whats new and what has changed in this latest release.
john@soulsolutions.com.au
John OBrien is a Director
of Soul Solutions, based in
Brisbane, Australia.
John is a Windows Live
Developer MVP and
moderates the Virtual Earth
forum on MSDN. He is part
of the core team that runs
the ViaWindowsLive.com
community site for Windows
Live technologies.
John has presented on
Windows Live technologies at
many events including Tech
Ed Australia, Museums and
the Web, and MSDN/SQL user
groups.
24
CoDe_FocusLive.indd 24
www.code-magazine.com
A tip, use the keyboard arrow keys and the dashboard rotate buttons to navigate between the images seamlessly. You can preview this amazing functionality at http://maps.live.com.
Additionally you get two new Birdseye methods in
the traditional 2D mode, first:
VEBirdseyeScene.GetBoundingRectangle();
www.code-magazine.com
CoDe_FocusLive.indd 25
25
Within 3D mode:
Ctrl-Q enters 1st person mode
Mouse operates viewpoint
W A S D (move around)
C (Zoom In)
SPACE (Zoom Out)
ESC (Exit)
26
CoDe_FocusLive.indd 26
www.code-magazine.com
www.code-magazine.com
CoDe_FocusLive.indd 27
27
Clearly it is uncommon
to actually know these coordinates
unless the data
is coming from a GPS device.
Mercator Projection
Virtual Earth 2D uses the
Mercator projection and
uses the WGS84 standard
for its coordinates in decimal
degrees. Essentially in order
to flatten a sphere onto a flat
surface this projection distorts
the earth horizontally while
maintaining accuracy vertically.
This distortion increases as you
move from the equator to the
poles. The side effect is that
countries like Greenland, at the
extreme, look significantly bigger
than in reality. Change to 3D
mode to see objects without this
distortion.
This functionality is only supported for paying Virtual Earth customers at this time.
Description
Code
English, Canada
en-ca
en-gb
en-us
Japanese, Japan
ja-jp
cs-cz
Danish, Denmark
da-dk
Dutch, Netherlands
nl-nl
Finnish, Finland
fi-fi
French, France
fr-fr
German, Germany
de-de
Italian, Italy
it-it
Norwegian, Norway
nb-no
Portuguese, Portugal
pt-pt
Spanish, Spain
es-es
Swedish, Sweden
sv-se
Chinese, China
zh-cn
28
CoDe_FocusLive.indd 28
www.code-magazine.com
www.code-magazine.com
CoDe_FocusLive.indd 29
Zindex
You can now change the Zindex of shapes. As
shapes can easily overlap, it is important to be able
to control which shape appears on top or behind.
This is the same concept as in applications like Microsoft PowerPoint, where you may send objects
backwards or forward in their Z index. Microsoft
has added three new methods to retrieve and set
Zindex for the icon (pushpin) and the line or polygon separately, collectively called the polyshape.
29
Number of Pins
0.008
0.004
10
0.066
0.022
100
0.632
0.209
500
2.883
1.477
1000
7.264
2.259
2000
21.831
5.644
VEShape.GetZIndex();
VEShape.GetZIndexPolyShape();
VEShape.SetZIndex(icon, polyshape);
Altitude
Within 3D mode, you can now position shapes at a
specific altitude. The VELatLong class now has two
extra properties:
VELatLong.Altitude
VELatLong.AltitudeMode
30
VEShape.SetMaxZoomLevel(level);
VEShape.SetMinZoomLevel(level);
CoDe_FocusLive.indd 30
www.code-magazine.com
Conclusion
Virtual Earth has grown into a mature application ready for use in demanding enterprise applications. The recent update added new functionality, improved the user interface, and increased the
performance while having no breaking changes.
Applications using version 5 may simply need to
change the version number to 6. However to support this, certain functionality from previous versions, such as the old routing method, still works
but has been marked as deprecated:
www.code-magazine.com
CoDe_FocusLive.indd 31
31
Jason Kelly
jasonk@akonasystems.com
http://blog.akonasystems.com
Jason Kelly is a senior
consultant at Akona Systems,
Inc. in Kirkland, Washington.
He is the development lead for
Akonas Windows Live Center
of Excellence and spends his
time helping customers create
solutions on the Windows Live
platform. Before joining Akona,
Jason worked for eight years
in software development at
Microsoft.
t takes an engaged audience and compelling exWindows Live Spaces Photo API. Just adding those
periences to reach success on the Web. Using
two services gives you full-motion video, user-genWindows Live Services, your site can provide
erated content, and photo albumsall hosted by
engaging experiences that conWindows Live and presented
nect directly with hundreds of
by your site.
Fast Facts
millions of Windows Live users.
The Windows Live Quick
But how do you start? Windows
Visitors to your site can also
Applications are fully
Live Quick Applications gives
communicate and stay connectfunctional Web applications
you an easy way to get started
ed with Windows Live Services.
by showing you how to build
Build Windows Live Messenger
that show how to use
new experiences for your cusinto your site so your users can
Windows Live Services
tomers with Windows Live Sercommunicate with one anto build compelling Web
vices. You can quickly and easother; integrate Windows Live
scenarios. The source code is
ily use Windows Live Services
Alerts to keep them connected
free to download and modify.
to give your users new ways to
anywhere on the network, even
Visit http://www.codeplex.
share information, communiwhen offline.
com/ WLQuickApps for
cate, and stay connected.
You dont have to create an auinformation and downloads.
Each Quick Application uses
thentication scheme for your
several Windows Live Services
users. Your server doesnt need
to store and share data in a fully functional Web
to host streaming media or run a database to keep
application. You can download the source code to
track of contacts. Just build the glueconnect the
learn about Windows Live development and modify
Windows Live Services together to create your own
the code to create your own site.
new user experience.
32
CoDe_FocusLive.indd 32
Tafiti
Tafiti is one of the newest Quick Applications. It mixes Live Search with Silverlight and Windows Live ID
to present a highly immersive search experience.
www.code-magazine.com
Figure 1: Tafiti integrates Windows Live Search with Silverlight and Windows Live ID to make Web
research an engaging experience.
Contoso ISV
Contoso ISV uses many of the Windows Live Services to build an online Customer Relationship
Management (CRM) application. This Quick App
glues together Silverlight Streaming, Windows
Live Messenger, Windows Live Alerts, and Virtual
Earth to demonstrate a business-focused Web application.
Windows Live Messenger enables several features
in Contoso ISV. The Windows Live Messenger
IM Control drops right into the Web site. It lets
visitors have instant messaging conversations with
Contoso staff without leaving the home page (Figure 2).
Several Windows Live Services come into play
when a customer schedules a meeting. Virtual
Earth is integrated with Windows Live Messenger
to schedule an appointment and get driving directions (Figure 3). When the sales staff schedules
the appointment, the company representative automatically receives a Windows Live Alert notifying them of the new appointment.
Contoso ISV also uses Silverlight Streaming to
deliver the video content displayed on the home
page. Silverlight Streaming offers free hosting of
videos and interactive content. Windows Live
www.code-magazine.com
CoDe_FocusLive.indd 33
Figure 2: Contoso ISV shows how to build a site that incorporates the Windows Live Messenger IM
control.
hosts and streams the media, relieving developers
of storage and scalability concerns.
To see this combination of Windows Live Services
in action, go to http://contosoisv.mslivelabs.com.
33
Windows Live
Services
The Windows Live Quick
Applications provide sample code
to get started developing with all
of the following Windows Live
Services:
Silverlight Streaming
Live ID
Live Search
Live Messenger
Virtual Earth
Live Alerts
Live Contacts
Live Spaces
Live Expo
Figure 3: Contoso ISV uses the Windows Live Messenger Activity SDK to integrate Virtual Earth and Windows Live Alerts
with Messenger.
34
CoDe_FocusLive.indd 34
www.code-magazine.com
Figure 4: Contoso Bicycle Club mixes content from Windows Live Spaces with geo-tagged data from Live Search Maps to
show the route of a bicycle ride.
Getting Started
I am building a site for home theater enthusiasts called
Ultimate Home Theater. The front page will show a blog
of the latest home theater news and will have a link to a
photo gallery. Users should be able to sign up for alerts
when new content is posted and the site needs a place
for users to buy and sell home theater equipment.
I want to get the site online as quickly as possible
without writing custom code to store and retrieve
blog posts, show pictures, or keep track of items for
sale. Thats where Windows Live Services save the
day: Windows Live takes care of uploading and hosting the data. I just write the glue code that calls the
Windows Live APIs and presents the data.
Ill start with Contoso Bicycle Club, because it already
has several features that I want to build into Ultimate
www.code-magazine.com
CoDe_FocusLive.indd 35
35
Listing 1: Photos.aspx.
<asp:Image ID="Slides" runat="server" Height="480"
ImageUrl="images/blank_slide.png"/>
<ajaxToolkit:SlideShowExtender ID="slides"
runat="server" TargetControlID="Slides"
SlideShowServiceMethod="GetSlides"
AutoPlay="true" UseContextKey="true"
Loop="true" />
36
CoDe_FocusLive.indd 36
www.code-magazine.com
Conclusion
Windows Live Services open up the features of Windows Live to any Web site with an easy-to-use developer platform. The wide array of services, simple
terms of use, and helpful documentation simplify
many aspects of modern Web development.
Quick Applications are rich sample applications designed to help you integrate Windows Live Services
into your Web site. More than just sample code,
Quick Applications are fully functional applications that you can customize and extend to build
your own site much more quickly than starting from
scratch.
The latest information on the Windows Live Services is at http://dev.live.com.
Jason Kelly
CoDe Magazine
www.code-magazine.com
5, 45
Devscovery Conferences
www.devscovery.com
51
2-3
83
Xiine
www.xiine.com
84
ADVERTISING INDEX
Advertisers Index
This listing is provided as a courtesy to our readers and
advertisers.
The publisher assumes no responsibility for errors
or omissions.
Advertising Sales:
Vice President,
Sales and Marketing
Tom Buckley
832-717-4445 ext. 34
tbuckley@code-magazine.com
Sales Managers
Erna Egger
+43 (664) 151 0861
erna@code-magazine.com
Tammy Ferguson
832-717-4445 ext 26
tammy@code-magazine.com
www.code-magazine.com
CoDe_FocusLive.indd 37
37
Building Personalized
Applications on the
Windows Live ID Platform
Vaishali De
vaishde@microsoft.com
Vaishali De has been a Program
Manager on the Windows Live
ID team since she graduated
from the University of Illinois
at Urbana-Champaign in
2004. She has worked on
a smorgasbord of features
including profile management,
rename, device authentication,
and service provisioning.
Apart from writing killer specs,
she loves fattening up her
colleagues with home-baked
goodies. With a wide range
of interests outside work, her
office reflects her colorful
personalityit is famous on
the Lakeridge campus for its
wall art.
38
CoDe_FocusLive.indd 38
Authentication
Windows Live ID Web Authentication helps you build identity-aware Web applications. It is a service that allows you to:
Verify the identity of visitors to your site.
Offer personalized access to your sites content to millions of Live ID users, who dont
need to create yet another identity.
Provide single sign-on from your application
to Windows Live services.
Seamlessly integrate the advanced, and useful,
functionality of Windows Live controls in a
non-programmatic way.
Access users Windows Live data with their
explicit consent.
www.code-magazine.com
Users Browser
Windows Live ID
Authentication Service
www.code-magazine.com
CoDe_FocusLive.indd 39
39
There is no certification or approvals process. Accept the Windows Live Terms of Use and youre all
set!
Listing 1: Handling different actions in the response from the Windows Live ID authentication service for Web Authentication.
//Handling a login action
If (action == "login")
{
WindowsLiveLogin.User user = wll.ProcessLogin(Request.Form);
//The ProcessLogin method parses, decrypts, and validates the
//encrypted authentication token received from the Windows Live ID
//authentication service, letting you access the user's unique ID
//easily
HttpCookie loginCookie = new HttpCookie("webauthtoken");
//Storing the authentication token in a cookie called
//"webauthtoken" to keep the user signed in to your site during
//multiple page views
if(user != null)
{
loginCookie.Value = user.Token;
if (user.UsePersistentCookie)
//The ProcessLogin populates the user object with properties like
//the user.UsePersistentCookie property. If UsePersistentCookie
//is true, your application is expected to use a persistent cookie
//to store the authentication token. A persistent cookie keeps
//the user signed in across multiple browser sessions
{
loginCookie.Expires = DateTime.Now.AddYears(10);
}
}
else
{
loginCookie.Expires = DateTime.Now.AddYears(-10);
}
Response.Cookies.Add(loginCookie);
Response.Redirect("default.aspx");
40
CoDe_FocusLive.indd 40
Response.End();
}
//Handling a clearcookie action
else if (action == "clearcookie")
{
HttpCookie loginCookie = new HttpCookie("webauthtoken");
//Deleting the current "webauthtoken" cookie
loginCookie.Expires = DateTime.Now.AddYears(-10);
Response.Cookies.Add("webauthtoken");
string type;
byte[] content;
wll.GetClearCookieResponse(out type, out content);
//GetClearCookieResponse returns a GIF image to the
//authentication server to indicate that the user has signed out
Response.ContentType = type;
Response.OutputStream.Write(content, 0, content.Length);
Response.End();
}
//Handling a logout action
else if (action == "logout")
{
HttpCookie loginCookie = new HttpCookie("webauthtoken");
//Deleting the current "webauthtoken" cookie
loginCookie.Expires = DateTime.Now.AddYears(-10);
Response.Cookies.Add("webauthtoken");
Response.Redirect("default.aspx");
//Redirecting users to the page on your Web application that is seen
//by users who are signed out
Response.End();
}
www.code-magazine.com
www.code-magazine.com
CoDe_FocusLive.indd 41
Sign Me Up!
Get the Windows Live ID Web
Authentication 1.0 SDK from
http://msdn2.microsoft.com/
en-us/library/bb676633.aspx.
Register your application at
https://msm.live.com/app/
default.aspx.
Get the Windows Live ID Client
Authentication 1.0 SDK from
http://msdn2.microsoft.com/enus/library/ bb404791.aspx.
41
Listing 2: What to do when the user clicks the Sign-in/Sign-out button in your client application.
//Event handler for Sign-in/Sign-out button clicks
private void buttonSignInOrOut_Click(object sender, EventArgs e)
{
//Check to see if the user is currently authenticated
if (!oID.IsAuthenticated)
{
try
{
//Try to authenticate the user by showing the
//Sign-in dialog window
if (oID.Authenticate())
{
currentUserName = oID.UserName;
}
else
{
MessageBox.Show("Authentication failed");
}
}
catch (WLLogOnException wlex)
{
if (wlex.FlowUrl != null)
{
MessageBox.Show(wlex.ErrorString + "Please go
to " + wlex.FlowUrl.AbsoluteUri + "to correct
the condition that caused the error");
}
else
{
MessageBox.Show(wlex.Error String);
}
Windows Live
Controls
Windows Live Controls allow
you to easily incorporate
cool functionality into your
applications. Visit https://dev.live.
com to learn more.
Create a mashup
of rich user content
from various
Live services in
your application
with the users
explicit consent
using the
Delegated
Authentication
technology.
42
else
{
//If user is authenticated, they intended to Sign-out. Try
//signing the user out.
try
{
oID.CloseIdentityHandle();
currentUserName = "";
}
catch (WLLogOnException wlex)
{
if (wlex.FlowUrl != null)
{
MessageBox.Show(wlex.ErrorString + "Please go to " +
wlex.FlowUrl.AbsoluteUri + "to correct the condition
that caused the error");
}
else
{
MessageBox.Show(wlex.ErrorString);
}
}
}
UpdateDisplay();
}
oIDMgr = IdentityManager.CreateInstance("BlogIt;
vaishali@contoso.com;BlogIt Application",
"Windows Live ID Client");
CoDe_FocusLive.indd 42
}
}
www.code-magazine.com
Implementing Authentication
Call the Authenticate method to authenticate the user.
This method shows the user the sign-in dialog box shown
in Figure 2. This standard dialog box allows the user to
enter their Windows Live ID credentials and makes it
really easy for you to log the user in. Listing 2 shows you
what you need to do when the user clicks the Sign-in/
Sign-out button. Declare oID as an instance of Identity
at the class level so that all your code can access it.
Implementing Personalization
A user personalizes your client application by specifying various data and settings to customize it. Every
time the user signs into your client, you load these data
and settings into the application. For example, users
could pick a background color for the application or
organize their Live contacts in a particular manner.
Your client:
Lets the user create data and settings for personalization.
Implementing Access to
Windows Live ID Sites and Services
Your client can access Windows Live ID sites and
services in the following ways:
Through a Web service API, such as SOAP or
XML-RPC.
Through an authenticated browser window.
For access through a Web service API, your code
will:
Authenticate the user with the Authenticate
method.
Obtain a service-specific ticket with the GetTicket method.
Windows Live
Delegated
Authentication
Windows Live Delegated
Authentication allows thirdparty applications to access
Live ID users information with
explicit user consent. For more
information, please refer to
Windows Live Delegated APIs
on page 46.
www.code-magazine.com
CoDe_FocusLive.indd 43
43
Listing 3: Continued
MessageBox.Show(wlex.ErrorString);
}
}
44
CoDe_FocusLive.indd 44
For IE 6.0 or 7.0, call the OpenAuthenticatedBrowser method. For browsers other than IE, invoke the execution of the browser and make sure
that the browser sends the appropriate authentication data in a form post to the Windows Live ID site
or service URL. Obtain this authentication data by
calling the GetNavigationData method.
Special thanks to Dave Shevitz and Vivek Nirkhe
for their help with this article.
Vaishali De
www.code-magazine.com
www.code-magazine.com/subscribe/ap37
CoDe_FocusLive.indd 45
Dr. Neil
Neil@Roodyn.com
Dr. Neil is an independent
itinerant consultant, trainer,
and author. He travels the
world working with software
companies. Dr. Neil loves
Australia, where he spends the
summer enjoying the Sydney
lifestyle and helping software
development teams get more
productive. Dr. Neil spends his
other summer each year flying
between northern Europe and
the USA working with software
teams and writing about his
experiences. Neil brings his
business and technical skills to
the companies he works with
to ensure that he has happy
customers. His latest book
eXtreme .NET (Addison Wesley,
2005) introduces eXtreme
Programming Techniques to
.NET developers. Dr. Neil is a
Microsoft Regional Director
and a Windows Live Developer
MVP.
http://ViaWindowsLive.com,
a Web site to help developers
build on Windows Live
services.
46
CoDe_FocusLive.indd 46
www.code-magazine.com
Permissions Granted
Once you have your AppID you will need to build a
handler page to receive a token known as a consent
token. This consent token will be sent to your application from Microsoft once a user has consented
to allow delegated authentication to your application. A consent token contains 4 important pieces
of information:
Persist the
Consent Token &
Owner Handle
(dependenton Resource)
Third
party.com
Data
Live ID
Delegation
Service
Delegation
Token
Expiresafter
short time span.
Resource
Provider
(e.g. Live Contacts)
ow
se
s
(e.g. Spaces)
(e.g. Storage)
Br
End
User
www.code-magazine.com
CoDe_FocusLive.indd 47
(e.g. Calendar)
47
If the service
requires that you identify your
application with an
application identifier,
you will need to obtain an
application ID from the Windows
Live Microsoft Service Manager
Everything as an Atom
The Atom Publishing Protocol (or AtomPub as
its often called) defines a simple protocol for performing CRUD (Create, Read, Update, and Delete)
operations on data over HTTP. Over the coming
months, most of the Windows Live Services will
provide offerings that conform to the AtomPub
standards. This is a fantastic move towards standardization of the Windows Live Services APIs.
In the last few years the APIs emerging from the
various Windows Live Services have been varied
and numerous. Each product group within Microsoft created their own API set, some were REST
based, some were SOAP, others were WebDav.
Standardizing on a single technology to access the
Windows Live Services will make our lives as developers easier.
48
CoDe_FocusLive.indd 48
Microsoft, Do It for Me
The new AtomPub services will be available for access through the delegated authentication mechanism described in the previous section. Combining these two technologies to create a well defined
mechanism for accessing, authenticating, and working with the Windows Live Services has the following implications:
The ADO.NET Data Services provides this templating technology. An ASP.NET AJAX library abstracts
www.code-magazine.com
want to perform, you call the executeActions method on the ActionSequence object and the batched
operation requests will be made.
var liveService =
new Sys.Data.DataService("xxxxxxx.live.com");
Photos Example
Standardizing on
a single technology to access
the Windows Live Services
will make our lives as
developers easier.
if (last != null)
{
photoSvc.LoadProperty(last, "PhotoBytes");
Console.WriteLine("Loaded picture of type '{0}'.
Launching in explorer...", last.PhotoMimeType);
string le = Path.GetTempFileName();
File.WriteAllBytes(le, last.PhotoBytes);
System.Diagnostics.Process.Start(le);
}
Album album;
// single album by key w/URL
album =
photoSvc.CreateQuery<Album>("/Albums(434)").Single();
Console.WriteLine(album.Name);
// create an album
Album myPics = new Album();
myPics.ID = 987;
myPics.Name = "Mix08";
photoSvc.AddObject("Albums", myPics);
photoSvc.SaveChanges();
Console.WriteLine("Created, Album ID " + myPics.ID);
www.code-magazine.com
CoDe_FocusLive.indd 49
}
}
49
Conclusion
Dr. Neil
System;
System.IO;
System.Collections.Generic;
System.Linq;
Microsoft.Data.WebClient;
System.Xml.Linq;
: base(url)
{
this.DataNamespace = "http://dev.live.com/photos";
this.SendingRequest += new EventHandler
<SendingRequestEventArgs>(SendingRequestHandler);
this.ReadingEntity += new EventHandler
<ReadingWritingEntityEventArgs>(ReadingEntityHandler);
}
void ReadingEntityHandler(object sender,
ReadingWritingEntityEventArgs e)
{
if (e.Entity is Photo)
{
((Photo)e.Entity).Title = e.Data.Element(atomns +
"title").Value;
}
}
50
CoDe_FocusLive.indd 50
www.code-magazine.com
CoDe_FocusLive.indd 51
52
CoDe_FocusLive.indd 52
Silverlight Streaming
Microsoft has a software and service strategy
and this is where the Silverlight Streaming by
Windows Live service comes indevelopers can
deploy their Silverlight applications and rich media in the cloud, leveraging Microsofts high
performance, high availability content distribution network.
While the product is in pre-release, storage
and delivery is free up to 4 GB, with outbound
streaming up to 700 Kbps. After release, developers will have continued use of the service with
up to 1 million minutes of free video streaming at
700 Kpbs per site per month.
www.code-magazine.com
You can sign up for a free Silverlight streaming account at http://silverlight.live.com. You need a Windows Live ID to get started or you can create a new
Windows Live ID for free.
Uploading
Now move your Hello World sample to the Silverlight Streaming Service.
First create a manifest.xml file, which describes the
constituent parts of your Silverlight Streaming application:
Figure 2: Uploading the application to Silverlight Streaming.
<SilverlightApp>
<version>1.0</version>
<source>Hello.xaml</source>
</SilverlightApp>
For this simple example, you no longer need the default.html or JavaScript files. You just need to create
a Hello.zip file that contains manifest.xml and Hello.
xaml.
On Windows, multiple select the files, right-click
and select Send To Compressed (zipped) folder
Listing 2: Default.htm.
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Hello World</title>
<script type="text/javascript" src="Silverlight.js"></script>
<script type="text/javascript" src="CreateSilverlight.js"></
script>
</head>
<body>
<div id="SilverlightPlugInHost">
<script type="text/javascript">
createSilverlight();
</script>
</div>
</body>
</html>
Listing 3: CreateSilverlight.js.
function createSilverlight()
{
Silverlight.createObjectEx({
source: 'Hello.xaml',
parentElement: document.getElementById
('SilverlightPlugInHost'),
id: 'SilverlightPlugIn',
properties: {
width: '400',
height: '400',
background:'#ffffff',
www.code-magazine.com
CoDe_FocusLive.indd 53
isWindowless: 'false',
version: '1.0'
},
events: {
onError: null,
onLoad: null
},
context: null
});
}
53
Where accountId is your Silverlight Streaming numeric account identifier and appName is the name
of your application (in this case Hello). You can
find out your accountId by clicking the Manage Account link. The IFRAME invoker redirects you to
an obfuscated URL as in Figure 5.
Figure 3: Having uploaded your application, test links and sample code are automatically created.
Expression Encoder
Hello World is a start, but what happened to the
rich multimedia I was talking about? One of the
easiest ways to get started with Silverlight video
and audio is using Expression Encoder.
You can download a Trial edition of Expression
Encoder from http://www.microsoft.com/expression.
Its simple and intuitive to use, but there is also a
short video tutorial available.
You can edit and encode digital video and audio,
add leaders, trailers, and watermarks and control
the quality and encoding of the output.
Figure 4: Click Launch Application Test Page to run your application.
Quick Applications
The Windows Live Quick
Applications are a great way to get
started with Silverlight Streaming
and Windows Live Services.
The Contoso Bicycle Club and
Contoso University samples both
include free, open source code
samples that make extensive use
of Silverlight Streaming.
http://dev.live.com/QuickApps
you can use any of the popular ZIP compression programs, but you need to make sure that the
manifest file appears in the top-level root of the
zip filezipping the parent directory is a common
error and will not work!
Log in to Silverlight Streaming at http://silverlight.live.com using your Windows Live ID and
click Manage Applications. Select Upload a Silverlight Application, specify a name (Hello)
and browse for your Hello.zip file. Click Upload
(Figure 2).
Depending on your connection speed, this may
take a while. If all goes well, you will be presented
with a page that allows you to test your application. You will also be given sample HTML and JavaScript that you can cut and paste into your own
Web site to run the application (Figure 3).
54
CoDe_FocusLive.indd 54
There are a number of predefined Silverlight media player templates in the Job Output section of
the Output tab and these will create for you a full
Silverlight wrapper without any coding.
If you download and install the Silverlight Streaming
Publishing Plug-In for Expression Encoder, you
can publish a job output from Microsoft Expression Encoder directly to Silverlight Streaming using
the public API. Just provide your accountID and
Account Key and press Publish (Figure 6).
www.code-magazine.com
Expression Blend 2
If you are serious about designing professional,
rich user experiences with Silverlight, you probably want to use Expression Blend 2. This is a
full-featured Silverlight XAML authoring tool for
designers.
Using Expression Blend 2 December Preview,
you can create a new Silverlight 1.0 Site project,
and then interact with the design surface to lay
out your graphic design. In Split view, you can see
your design work and the corresponding XAML
(Figure 7).
You can also open the same site in Visual Studio,
allowing developers to attach functionality and
enabling efficient designer/developer interaction.
Notes
You can upload and manage your Silverlight applications programmatically using a simple REST API.
You can use Expression Encoder with a command
line interface allowing batch mode operation and
on-the-fly trans-coding.
Figure 6: Microsoft Expression Encoder can automatically generate Silverlight media players from
predefined templates.
Conclusion
Video-enabled Web applications have traditionally been expensive and difficult to host because of
their high bandwidth demands and requirements
for streaming and edge-cached networks.
Silverlight is more than a Flash replacementits
changing the way we build rich interactive applications on the Web. Just take a look around to see a
wide range of applications including video, games,
and advanced data visualization tools.
Rob Blackwell
www.code-magazine.com
CoDe_FocusLive.indd 55
55
12.02.2008 23:49:29 Uhr
Sctt Lovegrove
scott@liveside.net
http://scottisafooldev.spaces.
live.com
Sctt is a Windows Live MVP
for Microsoft and is very
heavily involved with Windows
Live, not just with Windows
Live Writer. He is one of the
main writers for LiveSide.net, a
community Web site dedicated
to Windows Live and his main
area of blogging for LiveSide is
developing on Windows Live.
Sctt has written a number of
popular plugins for Windows
Live Writer and can often
be found in the Live Writer
Support forum, for both
general support and the
developer forums.
efore you can begin writing a plugin for WinWriting Your Plugin
dows Live Writer (http://writer.live.com/),
Open up Visual Studio and create a new Class Liyou need to understand what it is and what
brary project, giving it a meaningful name for your
it actually does. Windows Live Writer is a free
plugin. Rename the default class1.cs to plugin.cs (this
desktop blog authoring tool from Microsoft that
isnt essential, but will allow you to
allows you to write an entry
quickly see the main plugin class).
for your blog without having
Fast Facts
to be online and do it right
Windows Live Writer doesnt
Next you need to add the Windows
from your desktop. Live
Live Writer API reference: bring up
just support Microsofts
Writer doesnt just support
the Add Reference window, point
Microsofts own blogging
own Windows Live Spaces
to your Windows Live Writer insite (Windows Live Spaces),
blogging platform,
stall folder (typically C:\Program
it supports a multitude of
it supports a number of
Files\Windows Live\Writer\), and
different blog engines: basidifferent and popular blog
then select WindowsLive.Writer.
cally any that support the
engines, such as Wordpress
API.dll. As a best practice for this
MetaWeblog API or Atom
or Community Server.
reference, set the property of Copy
Publishing Protocol. This list
Local to be false for this reference
includes Wordpress, Com(this will stop older versions of the
munity Server, LiveJournal,
API DLL being copied into the Live Writer Plugins
and Blogger. You can write your blog entry in
folder). Open plugin.cs and include the following usthe style of your own blog as well because Live
ing statement:
Writer downloads your blog style and uses it as
a template.
using WindowsLive.Writer.Api;
56
CoDe_FocusLive.indd 56
www.code-magazine.com
System;
System.Collections.Generic;
System.Text;
WindowsLive.Writer.Api;
System.Windows.Forms;
namespace LiveWriterExample
{
[WriterPlugin("d2c99304-8648-4696-9ef1-6a82a2d070c9",
"LiveWriterExamplePlugin",
Description = "Makes highlighted text bold.",
HasEditableOptions = true,
ImagePath = "icon.gif",
Name = "Bold Text Plugin",
PublisherUrl = "http://www.liveside.net")]
[InsertableContentSource("Bold Text")]
www.code-magazine.com
CoDe_FocusLive.indd 57
57
Figure 1: What you need to get the plugin to copy to the plugins folder.
58
CoDe_FocusLive.indd 58
Using Forms
Windows Forms can be an integral part of your plugin, so its important to know how to call them
correctly from your plugin code. Forms can control
exactly what you want the user to put into their blog
entry. This can range from putting in video URLs,
selecting an emoticon from a range of different
emoticons, or even searching for a book from Amazon; you can use Forms in a multitude of different
ways.
You call the Form from within the CreateContent
method like so:
public override DialogResult CreateContent
(IWin32Window dialogOwner,
ref string content)
{
using (frmMain form = new frmMain())
{
DialogResult result = form.ShowDialog();
if (result == DialogResult.OK)
content = form.NewContent;
return result;
}
}
www.code-magazine.com
Using Settings
Settings, like Forms, can be an integral part of your
plugin if you would like the user to be able to set defaults for the plugin. Typically this would be done by
the user going to the Options area of Live Writer, selecting the plugin, and then choosing the Options button as shown in Figure 6.
To start with, Live Writer has to be told that your plugin has an options Form, which is done by making
sure you set HasEditableOptions=true in the Plugin
Attributes. Next you have to create a Settings class, as
this makes it easier to access the settings.
The Settings class also has to use WindowsLive.Writer.Api, as you need to pass it an IProperties object to
read/write the settings to. The constructor of your settings class should look like the following:
IProperties m_properties;
public PluginSettings(IProperties properties)
{
m_properties = properties;
}
Figure 5: Having used the plugin the highlighted text is now bold.
www.code-magazine.com
CoDe_FocusLive.indd 59
59
PluginSettings m_defaultsettings;
60
CoDe_FocusLive.indd 60
ContentSource plugins
are very basic plugins and will only
insert text into the blog entry.
You can edit SmartContentSource
plugins content again
at a later time.
SmartContentSource Plugins
SmartContentSource plugins have a lot more about
them than basic ContentSource plugins. The biggest
difference about the two types is that ContentSource
plugins insert HTML code into the blog entry and
this cannot be changed or edited using the plugin at
a later time. SmartContentSource plugins store as
much information about what code is inserted as the
developer wants it to, which allows the user to open
that blog entry in Writer at a later time and edit that
bit of their blog entry using the plugin without having
to go through the whole process again.
www.code-magazine.com
Listing 2: This is the code for the PluginSettings class in the SmartContentSource plugin.
using
using
using
using
System;
System.Collections.Generic;
System.Text;
WindowsLive.Writer.Api;
}
set
{
m_properties.SetString(PLACEHOLDER, value);
namespace EditPublish
{
public class PluginSettings
{
IProperties m_properties;
private const string PLACEHOLDER = "PLACEHOLDER";
private const string ACTUALCODE = "ACTUALCODE";
}
}
public string FinalText
{
get
{
return m_properties.GetString(ACTUALCODE, "");
}
set
{
m_properties.SetString(ACTUALCODE, value);
}
}
www.code-magazine.com
CoDe_FocusLive.indd 61
}
}
GeneratePublishHTML Method
In the main plugin class, there are three new methods that you can override: two of these are compulsory, the third is optional. The first of these is
the GeneratePublishHTML method, which is the
method where the HTML is what will be published
to your actual blog. This method is compulsory; you
have to have it there. This code snippet is a very
small example of what is required:
public override string GeneratePublishHtml
(ISmartContent content,
IPublishingContext publishingContext)
{
PluginSettings settings =
new PluginSettings(content.Properties);
return settings.FinalText;
}
In this snippet, the text that would actually be published comes from a setting that you would have
written to using the CreateContent method.
The IPublishingContext object that gets passed
holds information about the type of blog youre
61
Listing 3: This is the code for the plugin class for the SmartContentSource plugin.
using System.Windows.Forms;
using WindowsLive.Writer.Api;
}
public override SmartContentEditor CreateEditor
(ISmartContentEditorSite editorSite)
{
return new ContextEditor();
}
namespace EditPublish
{
[WriterPlugin("18d43e01-4549-4fde-8ca6-c7b4b7385fac",
"Insert Placeholder",
PublisherUrl = "http://scottisafooldev.spaces.live.com",
Description =
"Lets you put in a placeholder for the editor, "+
"to be replaced with other text when published.",
ImagePath = "writer.png",
HasEditableOptions = false)]
[InsertableContentSource("Placeholder")]
public class HiddenText : SmartContentSource
{
public override DialogResult CreateContent
(IWin32Window dialogOwner,
ISmartContent newContent)
{
PluginSettings settings =
new PluginSettings(newContent.Properties);
using (frmMain main = new frmMain(settings))
{
DialogResult result = main.ShowDialog();
return result;
}
writing to, which includes a GUID for the individual blog (this comes from Live Writer itself) and the Service Name, which is whatever
the current publishing service is (e.g., "Windows
Live Spaces", "LiveJournal", "WordPress.com",
etc.).
CreateEditor Method
This is the second compulsory method that you
need to override. This method creates the sidebar
that appears in Live Writer when a SmartContentSource object is selected in the Live Writer editor:
public override SmartContentEditor CreateEditor
(ISmartContentEditorSite editorSite)
{
return new ContextEditor();
}
GenerateEditorHTML
Sometimes in a plugin, what you want to display in
the blog entry isnt always something that you want
to appear in the editor of Live Writer, JavaScript
functions for example. So sometimes you might
need to have something else appear in the actual
Live Writer editing area. For this you need to override the GenerateEditorHTML method:
Figure 8: The sidebar in Live Writer appears on the right-hand side when a SmartContentSource is
selected.
62
CoDe_FocusLive.indd 62
www.code-magazine.com
Listing 3 shows the full code for the example plugins main class.
Using Forms
Using Forms is mostly the same as when doing a basic ContentSource plugin, the main difference being that instead of creating the final
Listing 4: The code for the main form in the SmartContentSource plugin.
using
using
using
using
using
using
using
System;
System.Collections.Generic;
System.ComponentModel;
System.Data;
System.Drawing;
System.Text;
System.Windows.Forms;
namespace EditPublish
{
public class frmMain : Form
{
PluginSettings m_settings;
public frmMain(PluginSettings settings)
{
m_settings = settings;
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (textBox1.Text != "")
{
m_settings.PlaceHolder = textBox1.Text;
}
else
{
MessageBox.Show("You need to set a placeholder",
"Big Fat Hairy Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
if (textBox2.Text != "")
{
m_settings.FinalText = textBox2.Text;
}
else
{
MessageBox.Show("Enter some text",
"Big Fat Hairy Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
this.DialogResult = DialogResult.OK;
this.Close();
}
/// <summary>
/// Required designer variable.
/// </summary>
www.code-magazine.com
CoDe_FocusLive.indd 63
63
Listing 4: Continued
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(13, 105);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(168, 13);
this.label1.TabIndex = 2;
this.label1.Text = "Text to appear in the Writer editor:";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(13, 185);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(189, 13);
this.label2.TabIndex = 3;
this.label2.Text = "Text to appear in the actual blog entry:";
//
// label3
//
this.label3.Anchor = ((System.Windows.Forms.AnchorStyles)
(((System.Windows.Forms.AnchorStyles.Top |
System.Windows.Forms.AnchorStyles.Left) |
System.Windows.Forms.AnchorStyles.Right)));
this.label3.Location = new System.Drawing.Point(13, 9);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(407, 96);
this.label3.TabIndex = 4;
this.label3.Text = resources.GetString("label3.Text");
//
// button1
//
this.button1.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.button1.Location = new System.Drawing.Point(264, 272);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 5;
this.button1.Text = "Insert";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// button2
//
this.button2.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.button2.Location = new System.Drawing.Point(345, 272);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(75, 23);
this.button2.TabIndex = 6;
this.button2.Text = "Cancel";
this.button2.UseVisualStyleBackColor = true;
//
// frmMain
//
this.AcceptButton = this.button1;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.button2;
this.ClientSize = new System.Drawing.Size(432, 307);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Controls.Add(this.label3);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Controls.Add(this.textBox2);
this.Controls.Add(this.textBox1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "frmMain";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Insert Placeholder Plugin";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private
private
private
private
private
private
private
}
}
HTML and passing that back, you just save the settings into the PluginSettings class, which will then be
used in a later method in the plugins main class.
face, it needs to inherit from the SmartContentEditor interface (make sure youre using WindowsLive.Writer.API):
64
CoDe_FocusLive.indd 64
System.Windows.Forms.TextBox textBox1;
System.Windows.Forms.TextBox textBox2;
System.Windows.Forms.Label label1;
System.Windows.Forms.Label label2;
System.Windows.Forms.Label label3;
System.Windows.Forms.Button button1;
System.Windows.Forms.Button button2;
The constructor for the editor has to be like the following or your plugin could end up with some strange
behavior:
PluginSettings m_settings;
ISmartContent m_content;
public ContextEditor()
{
InitializeComponent();
this.SelectedContentChanged +=
new EventHandler(
SelectedContentNowChanged);
}
www.code-magazine.com
System;
System.Collections.Generic;
System.ComponentModel;
System.Drawing;
System.Data;
System.Text;
System.Windows.Forms;
WindowsLive.Writer.Api;
namespace EditPublish
{
public class ContextEditor : SmartContentEditor
{
PluginSettings m_settings;
ISmartContent m_content;
public ContextEditor()
{
InitializeComponent();
this.SelectedContentChanged +=
new EventHandler(
SelectedContentNowChanged);
}
void SelectedContentNowChanged
(object sender, EventArgs e)
{
m_content = SelectedContent;
m_settings =
new PluginSettings(m_content.Properties);
textBox1.Text = m_settings.PlaceHolder;
textBox2.Text = m_settings.FinalText;
}
private void button1_Click
(object sender, EventArgs e)
{
if (textBox1.Text != "")
{
m_settings.PlaceHolder = textBox1.Text;
}
else
{
MessageBox.Show("No placeholder",
"Big Fat Hairy Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
if (textBox2.Text != "")
{
m_settings.FinalText = textBox2.Text;
}
else
{
MessageBox.Show("No text",
"Big Fat Hairy Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
OnContentEdited();
}
www.code-magazine.com
CoDe_FocusLive.indd 65
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources
/// should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.textBox1 = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.textBox2 = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.button1 = new System.Windows.Forms.Button();
this.label3 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(3, 91);
this.textBox1.Multiline = true;
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(178, 58);
this.textBox1.TabIndex = 0;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(0, 73);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(168, 13);
this.label1.TabIndex = 3;
this.label1.Text = "Text to appear in the Writer editor:";
//
// textBox2
//
this.textBox2.Location = new System.Drawing.Point(3, 182);
this.textBox2.Multiline = true;
this.textBox2.Name = "textBox2";
this.textBox2.Size = new System.Drawing.Size(178, 58);
this.textBox2.TabIndex = 4;
//
// label2
65
Listing 5: Continued
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(0, 164);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(171, 13);
this.label2.TabIndex = 5;
this.label2.Text = "Text to appear in actual blog entry:";
//
// button1
//
this.button1.Location = new System.Drawing.Point(3, 255);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 6;
this.button1.Text = "Apply";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// label3
//
this.label3.Anchor = ((System.Windows.Forms.AnchorStyles)
(((System.Windows.Forms.AnchorStyles.Top | System.
Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label3.BackColor = System.Drawing.Color.White;
this.label3.Font = new System.Drawing.Font("Microsoft
Sans Serif", 14F, System.Drawing.FontStyle.Regular,
System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label3.Location = new System.Drawing.Point(0, 0);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(190, 32);
this.label3.TabIndex = 7;
this.label3.Text = "Insert Placeholder";
//
// ContextEditor
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.label3);
this.Controls.Add(this.button1);
this.Controls.Add(this.label2);
this.Controls.Add(this.textBox2);
this.Controls.Add(this.label1);
this.Controls.Add(this.textBox1);
this.Name = "ContextEditor";
this.Size = new System.Drawing.Size(190, 482);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private
private
private
private
private
private
System.Windows.Forms.TextBox textBox1;
System.Windows.Forms.Label label1;
System.Windows.Forms.TextBox textBox2;
System.Windows.Forms.Label label2;
System.Windows.Forms.Button button1;
System.Windows.Forms.Label label3;
}
}
The code for the EventHandler method is also important to get right:
Listing 5 shows you the code needed for the sample plugins ContextEditor.
void SelectedContentNowChanged
(object sender, EventArgs e)
{
m_content = SelectedContent;
m_settings =
new PluginSettings(m_content.Properties);
textBox1.Text = m_settings.PlaceHolder;
textBox2.Text = m_settings.FinalText;
}
As a best practice, you should also use this EventHandler method to either set the current settings
to what you have in your sidebar or call the method that applies these settings.
66
CoDe_FocusLive.indd 66
www.code-magazine.com
Bronwen Zande
f you arent familiar with Live Search, it is located at http://www.live.com. Figure 1 shows the
Live Search home page. In addition to a standard search service, Live Search offers searches in
various categories such as images, news, maps, and
more.
and non-commercial sites at no cost. The full business terms are located at http://dev.live.com.
Bronwen@soulsolutions.com.au
+61 402 148 104
Bronwen Zande is a Director
of Soul Solutions, based in
Brisbane, Australia.
With over 10 years of software
development experience,
Bronwens primary focus
is Microsoft Live and .NET
development. She is a
Windows Live Services MVP
and part of the core team that
runs the ViaWindowsLive.com
community site for Windows
Live technologies.
When not working with
Windows Live, Bronwen helps
bring together GeekGirls
from around the globe at
http://www.geekgirlblogs.com.
www.code-magazine.com
CoDe_FocusLive.indd 67
Figure 1:
Fi
1 Th
The Li
Live S
Search
h hhome page.
67
Vikas Ahuja
Program Manager, Windows
Live Developer Platform,
Microsoft Corporation
With over ten years of
experience delivering IT
solutions, Vikas lives in
Redmond with his wife. He
previously worked with the
Microsoft.com Web site, held
different positions in quality
assurance, and is currently
handling program management
for the Windows Live
Developer Platform.
Contacts
68
CoDe_FocusLive.indd 68
www.code-magazine.com
www.code-magazine.com
CoDe_FocusLive.indd 69
<script type="text/javascript">
function Contacts1_OnClientData(sender, args)
{
var s = args.contacts.length+ " records\r\n";
for (var i = 0; i < args.contacts.length; i++){
for (var j in args.contacts[i]){
s += j + ": " + args.contacts[i][j]+"\r\n";
}
s += "\r\n";
}
alert(s);
}
</script>
69
The declaration for the Contacts control on the default.aspx Web page would look like:
<live:Contacts ID="Contacts1" runat="server"
DataDesired="rstname, lastname,
personalstreet, personalcity,
personalstate, personalcountry,
personalpostalcode"
Height="500px"
PrivacyStatementURL="~/privacyPolicy.htm"
View="List"
Width="250px"
OnClientData="Contacts1_OnClientData"
OnServerData="Contacts1_OnServerData" />
Listing 2: Default.aspx.
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register Assembly="Microsoft.Live.ServerControls"
Namespace="Microsoft.Live.ServerControls" TagPrex="live" %>
<html xmlns=http://www.w3.org/1999/xhtml
xmlns:devlive="http://dev.live.com">
<head runat="server">
<title>CoDe Magazine Article</title>
</head>
<body>
<form id="frmDemoArticle" runat="server">
<asp:ScriptManager ID="scmMgr" runat="server">
</asp:ScriptManager>
<script type="text/javascript">
function Contacts1_OnClientData(sender, args)
{
var s = args.contacts.length+ " records\r\n";
for (var i = 0; i < args.contacts.length; i++){
for (var j in args.contacts[i]){
s += j + ": " + args.contacts[i][j]+"\r\n";
}
s += "\r\n";
}
alert(s);
}
function Contacts1_OnClientCommit(sender, args){
alert('Contacts1_OnClientCommit event signaled');
}
</script>
<div>
<live:Contacts ID="Contacts1" runat="server"
DataDesired="rstname, lastname, personalstreet,
personalcity, personalstate, personalcountry,
personalpostalcode"
Height="350px" Width="250px" View="List"
70
CoDe_FocusLive.indd 70
PrivacyStatementURL="~/privacyPolicy.htm"
OnClientData="Contacts1_OnClientData"
OnClientCommit="Contacts1_OnClientCommit"
OnServerData="Contacts1_OnServerData"
OnServerCommit="Contacts1_OnServerCommit" />
<br />
<asp:UpdatePanel runat="server">
<ContentTemplate>
<asp:TextBox ID="txtEmail" runat="server"
Height="26px" Width="160px">
</asp:TextBox>
<asp:Button ID="btnAdd" runat="server"
Height="26px" Text="Add Contact"
onclick="btnAdd_Click" />
<br /><br />
<asp:Button ID="btnAddList" runat="server"
Text="Add List of Contacts"
onclick="btnAddList_Click" />
<asp:Button ID="btnDeleteList" runat="server"
Text="Delete List of Contacts"
onclick="btnDeleteList_Click" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnAdd"
EventName="Click" />
<asp:AsyncPostBackTrigger ControlID="btnAddList"
EventName="Click" />
<asp:AsyncPostBackTrigger ControlID="btnDeleteList"
EventName="Click" />
</Triggers>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
www.code-magazine.com
Listing 3: Default.aspx.cs.
using
using
using
using
using
using
using
using
using
using
using
using
using
using
System;
System.Data;
System.Conguration;
System.Linq;
System.Web;
System.Web.Security;
System.Web.UI;
System.Web.UI.WebControls;
System.Web.UI.WebControls.WebParts;
System.Web.UI.HtmlControls;
System.Xml.Linq;
Microsoft.Live.ServerControls;
System.Collections.Generic;
System.Diagnostics;
www.code-magazine.com
CoDe_FocusLive.indd 71
Registering Your
Application with
Windows Live ID
objContact.EmailPersonal =
txtEmail.ToString().Trim();
objContacts.Add(objContact);
Contacts1.CreateContacts(objContacts);
Contacts1.CommitContacts();
}
71
Microsoft Silverlight
Streaming Service
Microsoft Silverlight Streaming
Service by Windows Live offers
designers and Web developers
an easier and free solution for
hosting and streaming crossplatform, cross-browser media
experiences and rich interactive
applications (using Microsoft
Silverlight) that run on Windows
and Mac. To get a free Silverlight
Streaming service account,
please visit:
http://silverlight.live.com
DeleteContacts) and the user approves the operation, a delete request is posted to Windows Live servers. After the request completes, the OnClientCommit event is raised followed by the OnServerCommit
event. Figure 4 shows the event argument returned
on the client-side args, which reports an error for the
attempt to delete the nonexistent contact.
The Contacts control also offers other events for
sign-in/sign-out, error handling, and properties for
styling (text, color, height, and width). The reference for the Contacts control is available online at
http://dev.live.com/tools/contactsapi.aspx.
IDLoginStatus
IDLoginStatus provides Windows Live ID authentication, which can be used to identify visitors to
your Web site. IDLoginStatus provides a unique,
site-specific identifier for each Windows Live user.
This allows the Web site to personalize the experience for the visiting user.
Figure 5: IDLoginStatusyou
can get a new application ID from
within Visual Studio by clicking
Create new Application ID.
When a user clicks the Sign-in link, the IDLoginStatus control redirects to the sign-in Web page on
Windows Live servers (http://login.live.com) along
with an application ID. After the user enters their
credentials, the sign-in page redirects the user to the
page with the IDLoginStatus control.
To obtain an application ID for your Web site, you
need to register your application with the Windows
Live ID service. You can do so by visiting http://
msm.live.com/app (see sidebar: Registering Your
Application with Windows Live ID).
IDLoginStatus provides an easy workflow for developers within the Visual Studio development environment. After you drag-and-drop the IDLoginStatus control onto your Web page, you can get a
new application ID by clicking Create new Application ID from the IDLoginStatus tasks (Figure 5).
After you complete the registration of your application and close the form, the IDLoginStatus control
saves the application ID and application secret into
Web.Config and sets the ApplicationIDConfigKey
and ApplicationSecretConfigKey properties on the
IDLoginStatus control. The control adds wll_appid and wll_secret keys into the <appSettings> section of the Web.Config file. At run time, the control
checks the values of ApplicationIDConfigKey and
72
CoDe_FocusLive.indd 72
IDLoginView does
template switching and association
of Windows Live ID and ASP.NET
membership profiles.
If you are using ASP.NET membership, IDLoginStatus enables single-sign-on. You can set the AutomaticallyConvertAuthentication property to true.
When this property is set to true, the IDLoginStatus control verifies whether the current signed-in
user has previously associated with an ASP.NET
membership profile and automatically logs-in to
ASP.NET membership on existence of an association. Read more about this in IDLoginView.
You can find the complete reference for the IDLoginStatus control at http://dev.live.com/tools/idloginapi.aspx.
www.code-magazine.com
Listing 4: IDLoginView.aspx.
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="IDLoginView.aspx.cs" Inherits="IDLoginView" %>
<%@ Register Assembly="Microsoft.Live.ServerControls"
Namespace="Microsoft.Live.ServerControls"
TagPrex="live" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>CoDe Magazine Article - IDLoginView</title>
</head>
<body>
<form id="frmIDLoginView" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div>
<live:IDLoginStatus ID="IDLoginStatus1" runat="server" />
<br />
<live:IDLoginView ID="IDLoginView1" runat="server"
AutomaticallyAssociateAuthentication="True"
PromptOnAssociation="True">
<AnonymousTemplate>
<asp:Login ID="Login1" runat="server"></asp:Login>
<br />
This is anonymous template
</AnonymousTemplate>
<AssociatePromptTemplate>
Associate your user name for this Website
with your Windows Live ID?<br>
<asp:Button runat="server"
CommandName="associate_yes"
Text="Yes" Width="55px"
IDLoginView
The IDLoginView control extends ASP.NETs LoginView control. Where the LoginView control provides template switching based on a users logged-in
state in ASP.NET membership, IDLoginView provides switching based on a users logged-in state in
both ASP.NET membership and Windows Live ID.
IDLoginView adds three new templates in addition
to the two provided in the LoginView control:
AnonymousTemplate: Displayed to Web site
users who are not logged into the Web site (inherited from LoginView).
ID="IDLoginView1_livepromptyes">
</asp:Button>
<asp:Button runat="server"
CommandName="associate_no"
Text="No" Width="55px"
ID="IDLoginView1_livepromptno">
</asp:Button>
</AssociatePromptTemplate>
<LoggedInTemplate>
<asp:LoginStatus ID="LoginStatus1"
runat="server" />
This template is for ASP.NET logged in users
</LoggedInTemplate>
<LoggedInIDTemplate>
<asp:Login ID="Login1" runat="server">
</asp:Login><br />
This template is for Windows Live ID
signed in users
</LoggedInIDTemplate>
<LoggedInAllTemplate>
This template is for users logged in both
Windows Live ID and ASP.NET membership<br />
<asp:Button ID="btnRemove" runat="server"
Text="Remove Association"
onclick="btnRemove_Click" />
</LoggedInAllTemplate>
</live:IDLoginView>
</div>
</form>
</body>
</html>
Listing 5: IDLoginView.aspx.cs.
using
using
using
using
using
using
using
using
using
using
using
using
using
System;
System.Collections;
System.Conguration;
System.Data;
System.Linq;
System.Web;
System.Web.Security;
System.Web.UI;
System.Web.UI.HtmlControls;
System.Web.UI.WebControls;
System.Web.UI.WebControls.WebParts;
System.Xml.Linq;
Microsoft.Live.ServerControls;
www.code-magazine.com
CoDe_FocusLive.indd 73
73
74
You may be surprised to see that all of the template switching and association functionality can
be realized without you having to write a single
line of code.
When a Web site visitor signs-in to your Web page
using the IDLoginStatus control, IDLoginStatus
sets the webauth cookie, which contains the ApplicationUserID for the signed-in user. The IDLoginView detects the state change after the IDLoginStatus control sets this cookie. IDLoginView then
switches the template to the LoggedInIDTemplate
and renders the specified contents. You can provide the content applicable to users having Windows Live ID in this template. Then, if a user
signs-in to ASP.NET membership, IDLoginView
switches to the LoggedInAllTemplate. At this time,
if you had set the AutomaticallyAssociateAuthentication and PromptOnAssociation properties to
true, IDLoginView renders the AssociatePromptTemplate to the user. If the user chooses to associate the two identities, IDLoginStatus creates an
association between Windows Live ID and ASP.
NET membership.
The btnRemove_Click event handler (Listing 5)
shows how a developer can remove this association, if the user so chooses.
AssociationManager
Having set up the users for the Web site, you can
test the template switching and association fea-
CoDe_FocusLive.indd 74
SilverlightStreamingMediaPlayer
www.code-magazine.com
$nd("StreamingMediaPlayer1");
objSLSMPlayer.set_mediaSource("streaming:
/20709/VideoLibrary/Assets/Lake.wmv");
}
</script>
Details about the underlying ASP.NET MediaPlayer are available at this link: http://quickstarts.asp.
net/3-5-extensions/silverlight/MediaPlayerControl.
aspx.
Wrapping Up
www.code-magazine.com
CoDe_FocusLive.indd 75
75
Jon Arking
Jonarking@hotmail.com
Jon Arking is an independent
systems architect, trainer, and
author working in the greater
Philadelphia region. He spends
his time consulting on large,
enterprise systems on both
Microsoft and non-Microsoft
platforms. His most recently
published work, Professional
Windows Live Programming
from Wrox Press, 2007, is
the definitive handbook for
developers looking to build
Live-powered applications and
understand the Windows Live
business life cycle. Jon lives
with his wife and children in
south Jersey where he also
consults regularly for the City
of Philadelphia.
76
CoDe_FocusLive.indd 76
www.code-magazine.com
www.code-magazine.com
CoDe_FocusLive.indd 77
the power
behind Windows
Live Admin Center
lies not in the
simple creation
of accounts,
but rather in the
power that drives
Windows Live ID
and in the power of
service integration
and site federation.
77
78
CoDe_FocusLive.indd 78
www.code-magazine.com
www.code-magazine.com
CoDe_FocusLive.indd 79
Youll need to first create a Visual Studio .NET Console Application project and create a reference to the
Admin Center Web service endpoint.
1.
2.
79
Figure 5: Adding a Web reference to the Admin Center Web service endpoint.
Open Membership
One of the more interesting
features of Windows Live Admin
Center is the Open Membership
option. Using a prepared HTML
module that Webmasters can
customize in the Admin Center
administration pages, users can
create their own e-mail accounts
inside of your domain. Like all
Admin Center member accounts,
each name becomes its own Live
ID. That means that a user not
only gets an e-mail account with
your domain name, but also a
Live Spaces account, a Live Expo
account, and much more.
Open Membership is an ideal
way to generate more traffic to
your domain and each name
created helps to promote your
Web site. Whats more, Open
Membership takes a lot of the
hassle of account management
away from Webmasters and
places it squarely on the
shoulders of Windows Live.
However, the Open Membership
option may not be suitable for
Web sites that require a specific
registration process or those that
need to approve users before
their accounts can be activated.
Therefore, administrators can
choose to enable or disable this
option as they see fit.
80
CoDe_FocusLive.indd 80
3.
4.
5.
6.
using System.IO;
using System.Net;
This may seem like a lot of work at first, but it becomes a no-brainer once you get used to it. In the
Program.cs file, add the following code directly below
your static void Main function:
private static string CreateAuthTicket()
{
}
Youll call this function from the Main method directly, isolating all of the requisite tasks for generating
the ticket from the Main functions code.
Before you can create user accounts and view domain information, youll need to create a valid ad-
www.code-magazine.com
srvcAuth.authorizationType = MyAdminCenterSample.AdminCenterAPI.
ManageDomain2AuthorizationType.PassportTicket;
srvc.ManageDomain2AuthorizationValue = srvcAuth;
return loginTicket;
if (srvc.VerifyAuthData(loginTicket))
{
AdminCenterAPI.ManageDomain2Authorization srvcAuth = new
AdminCenterAPI.ManageDomain2Authorization();
else
throw new ApplicationException("An error occurred while
attempting to create an authorization ticket");
newStream.Write(tmpBytes, 0, tmpBytes.Length);
// Get the response
response = (HttpWebResponse)request.GetResponse();
// Return the result
string result =
new StreamReader(response.GetResponseStream()).
ReadToEnd();
request = (HttpWebRequest)WebRequest.Create(URL);
request.Method = "POST";
request.ContentLength = postContent.Length;
request.UserAgent = "Mozilla/4.0 (compatible;"+
"MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322)";
newStream.Close();
return result;
www.code-magazine.com
CoDe_FocusLive.indd 81
Go ahead and compile the code now and everything should come through fine. Youre now ready
to start creating your user accounts.
81
switch (response)
{
case "1":
Console.ReadLine();
break;
Console.WriteLine("Creating the"+
"authorization ticket...");
case "2":
Console.WriteLine();
break;
case "3":
break;
Console.WriteLine("Authentication completed.");
case "4":
break;
while (blnContinue)
{
Console.WriteLine();
Console.WriteLine();
Console.WriteLine();
case "5":
break;
case "6":
break;
case "7":
blnContinue = false;
break;
Console.WriteLine();
Console.WriteLine("1. Add a New User");
Console.WriteLine("2. View Member List");
Console.WriteLine("3. Enumerate"+
" registered domains");
Console.WriteLine("4. Rename a Member");
Console.WriteLine("5. Reset Member Password");
Console.WriteLine("6. Delete a User");
Console.WriteLine("7. Exit");
string response = Console.ReadLine();
default:
Console.WriteLine("You have not"+
" entered a valid response.");
break;
}
}
}
82
CoDe_FocusLive.indd 82
ne at
le onli
e artic om/focus/wl
ir
t
n
e
.c
his
agazine
Read t
.code-m
w
w
/w
:/
http
www.code-magazine.com
CoDe_FocusLive.indd 83
CoDe_FocusLive.indd 84