Windows Live Tools for Microsoft Visual Studio enables developers to incorporate a set of Windows Live services into their Web sites using Visual Studio and ASP.NET.

Using the Contacts ASP.NET Server Control, your users can easily share their contacts between Windows Live and your Web site. With the SilverlightStreamingMediaPlayer ASP.NET Server Control, you can show videos on your Web site from your Silverlight Streaming account with just drag-and-drop. The IDLoginStatus and IDLoginView ASP.NET Server Controls provide Windows Live ID authentication at your Web site for your users. Microsoft released its second community technology preview (CTP) in December, 2007. You can download this CTP from http://dev.live.com/tools.

Through this CTP, Microsoft is releasing four ASP.NET Server Controls: Contacts, IDLoginStatus, IDLoginView, and SilverlightStreamingMediaPlayer. To help you develop Windows Live Web sites, Microsoft has created a project template as well. This release only works with Visual Studio 2008 and Visual Web Developer 2008 Express Edition at this time.

A key aspect to note is that the user is in control of their data.

Installation of the Windows Live Tools is straightforward. After installation is complete, Visual Studio displays an “ASP.NET Windows Live Web Site” project template in the File | New Web Site dialog box (Figure 1). Also, you can find these controls listed as “Windows Live Tools” in the Toolbox.

![Figure 1: ASP.NET Windows Live Web site template.](https://codemag.com/Article/Image/0804102/Ahuja_Figure 1.tif)

Creating Your First Project with the Windows Live Tools

To start your first project that integrates Windows Live services, navigate to File | New Web Site, and select the “ASP.NET Windows Live Web Site” template. Fill out the details to proceed with project creation. Open the Default.aspx Web page in designer mode by choosing “View Designer” from the context menu in the Solution Explorer.

This article will drill down into each of the newly introduced controls and what they offer for your Web site.

Contacts

Have you ever wondered why you have to enter a new shipping address for each Web site whenever you buy a gift for a friend? What if you could share the shipping address across multiple Web sites using a central address book? The Contacts control is a solution that allows you to safely transfer your contact information between Windows Live Contacts (a user’s single address book between Windows Live Messenger and Windows Live Hotmail) and the shopping Web site. Also, the Contacts control can help a Web site build viral communication channels where users can message one another the context of the Web site. For example, a shopping Web site can specify a promotion message that their users can send one another from the Web site.

The Contacts control offers three different views to best suit your needs: Tile, TileList, and List. In Tile/TileList views, Web site users can start an IM conversation or open an e-mail with a pre-defined message/custom greeting from the Web site, such as “Let’s discuss this topic.” List view allows users to select and share their Windows Live Contacts across multiple Web sites and centralize address book management in one place. It’s an off-the-shelf address book pre-filled with data for any Web site on the Internet.

The user maintains control of the data and has the authority to choose to share or not share their data with your Web site.

I’ll show you how easy it is to use Windows Live Contacts in your Web site. Drag-and-drop the Contacts ASP.NET Server Control from the Toolbox onto the Default.aspx Web page. The drag-and-drop operation adds the privacyPolicy.htm file to your project (you can replace this file with your own privacy policy statement). Run the Web site by hitting Ctrl+F5. Visual Studio, after compiling the Web site, launches the browser and displays Default.aspx. You will need to sign in using your Windows Live ID. After you are signed-in, the Contacts control renders your contacts from messenger and Hotmail. Figure 2 shows the Contacts control with its default settings.

![Figure 2: The Contacts control (TileList view).](https://codemag.com/Article/Image/0804102/Ahuja_Figure 2.tif)

Sharing Contacts Data

The Contacts control maintains secure data isolation between Windows Live Contacts and your Web site.

The control fetches your user’s contacts data from Windows Live servers via a secure HTTPS connection. The user selects the contacts that they want to share with your Web site, initiates the sharing of data, and reviews what data is being shared. Only then is any data released to your Web site.

Another key aspect that requires special mention is the privacy statement for your Web site. The Contacts control requires that you provide a privacy statement URL. The Contacts control renders a privacy statement URL to the user while transferring contact information to your Web site. In your privacy statement, you must clearly state the usage of the data being transferred. You can either discard this data after use or store it in your servers for future usage. If you choose to store the data, you should clearly state this in your privacy statement and provide a means for the user to review or delete the stored data.

To enable sharing contacts data for the shipping address scenario as mentioned earlier, you would need to:

  • Set the PrivacyStatementURL to a Web page/link that describes the privacy statement for your Web site.
  • Set the View property to List.
  • Set the DataDesired property to specify which data elements need to be fetched from Windows Live Contacts.
  • Provide client/server-side event handlers to receive the data and handle the shipping process for the purchased items.

Next, I’ll show you how to modify the project to allow users to share their contacts data on Default.aspx. You can get the complete reference to the data elements allowed for the DataDesired property at http://dev.live.com/tools/contactsapi.aspx. Set the following values for the DataDesired property in the property grid for the Contacts control: firstname, lastname, personalstreet, personalcity, personalstate, personalcountry, and personalpostalcode.

Once data is transferred by the Contacts control, you can process the data in the OnClientData or OnServerData event handlers.

The event handler for OnClientData (in JavaScript) can look like the following:

<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>

Once you execute this code, you will notice that an alert comes up, which enumerates the data elements and their values (Figure 3). The OnClientData event handler receives the transferred contacts as an array of objects. Each object represents one contact selected by the user for transfer. Each contact object has data elements corresponding to the DataDesired property. If a certain data element does not exist for a contact, it will not be returned.

![Figure 3: Alert message showing contact details.](https://codemag.com/Article/Image/0804102/Ahuja_Figure 3.tif)

You can also specify similar processing logic in server-side code. The Contacts control offers a corresponding server-side event for processing data received from the transfer (Listing 1).

The declaration for the Contacts control on the default.aspx Web page would look like:

<live:Contacts ID="Contacts1" runat="server"
    DataDesired="firstname, lastname,
            personalstreet, personalcity,
            personalstate, personalcountry,
            personalpostalcode"
   Height="500px"
   PrivacyStatementURL="~/privacyPolicy.htm"
   View="List"
   Width="250px"
   OnClientData="Contacts1_OnClientData"
   OnServerData="Contacts1_OnServerData" />

Writing Contacts Data

The Contacts control allows you to write into a user’s address book. For example, a Web page may allow users to transfer Contacts data from their Web site to Windows Live Contacts. When modifications are being attempted to a user’s address book, an alert is raised notifying the user. Users are then required to review the modification and approve. Once approved, the modifications are transmitted to Windows Live servers via a secure HTTPS connection. Again, the user is in control of their data in this case as well.

IDLoginView does template switching and association of Windows Live ID and ASP.NET membership profile.

For example, adding a contact to a signed-in user’s address book is very simple. The Contacts control provides the CreateContact method, which takes a list of contacts (List<Contact*>).* The Microsoft.Live.ServerControls namespace contains the definition of the Contact class. The Contact class has member properties that represent a contact’s data elements. A complete list of data elements is available at http://dev.live.com/tools/contactsapi.aspx.

To demonstrate this, refer to Listing 2 and Listing 3. Listing 2 shows Default.aspx and Listing 3 shows Default.aspx.cs. Default.aspx has a Contacts control, an update panel, a text box where users can input e-mail for the contact to be added, and three button controls: adding a contact, adding a list of contacts, and deleting contacts.

The event handler, btnAdd_Click (defined in Listing 3), shows that it is very easy to add contacts to a user’s contacts. You start with creating a Contact object-set the data elements that you are interested in, create a generic List of contacts, and then pass it to the CreateContacts method. The Contacts control can then either abort or commit the operation. The following code snippet only shows how to set this for e-mail; however, you can extend the code to set whatever data elements your application desires:

//add contact to signed-in users' contacts
protected void btnAdd_Click(object sender, 
                  EventArgs e)
{
    List&lt;Contact&gt; objContacts = new
               List&lt;Contact&gt;();

    Contact objContact = new Contact();

    objContact.EmailPersonal =
 txtEmail.ToString().Trim();
    objContacts.Add(objContact);

    Contacts1.CreateContacts(objContacts);
    Contacts1.CommitContacts();
}

Listing 3 also has btnAddList_Click, which you use to submit multiple contacts for addition. You can submit a maximum of 30 contacts in one operation. Use btnDeleteList_Click to perform batch deletions of contacts. You will notice that you must call the CommitContacts method after create or delete operations; otherwise, these operations won’t be finalized. btnDeleteList_Click also highlights how errors are reported back from create/delete operations. In btnDeleteList_Click, the code is attempting to delete four contacts where the fourth contact was never added. Once the CommitContacts method executes (after 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.

![Figure 4: Client-side error reporting with the OnClientCommit event.](https://codemag.com/Article/Image/0804102/Ahuja_Figure 4.tif)

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.

When a user clicks on 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 ApplicationSecretConfigKey properties and reads the Web.Config keys.

![Figure 5: IDLoginStatus-you can get a new application ID from within Visual Studio by clicking “Create new Application ID”.](https://codemag.com/Article/Image/0804102/Ahuja_Figure 5.tif)

The following snippet from Web.Config highlights this:

&lt;appSettings&gt;
  &lt;add key="wll_appid" value="FF167FFE80FFF932" /&gt;
  &lt;add key="wll_secret" value="CoDeMagazine123" /&gt;
&lt;/appSettings&gt;

The HTML declaration for IDLoginStatus looks like the following:

&lt;live:IDLoginStatus ID="IDLoginStatus1"
    runat="server"
    ApplicationIDConfigKey="wll_appid"
    ApplicationSecretConfigKey="wll_secret" /&gt;

IDLoginStatus offers both client side and server side events for sign-in/sign-out. IDLoginStatus also returns AuthEventArgs, which contains the ApplicationUserID, TimeStamp (the time the user authenticated in seconds measured from Jan 1, 1970 GMT), and ApplicationContext (a parameter to round trip your application state through the redirections to and from the Windows Live servers). The ApplicationUserID is the unique site-specific identifier for the signed-in user.

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.

IDLoginView

The IDLoginView control extends ASP.NET’s LoginView control. Where the LoginView control provides template switching based on a user’s logged-in state in ASP.NET membership, IDLoginView provides switching based on a user’s 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).
  • LoggedInTemplate: Displayed to Web site users who are logged into ASP.NET membership at the Web site (inherited from LoginView).
  • LoggedInIDTemplate: Displayed to Web site users who are logged in with Windows Live ID at the Web site.
  • LoggedInAllTemplate: Displayed to Web site users who are logged into both ASP.NET membership and Windows Live ID.
  • AssociatePromptTemplate: Displayed to Web site users when they have logged in with both ASP.NET membership and Windows Live ID, but have not yet associated these two identities.

Not only does IDLoginView provide template switching based on a user’s logged-in state, but it also allows association of Windows Live ID and ASP.NET membership identities. Based on your choice, the AssociatePromptTemplate is presented to the user asking whether they want to associate their Windows Live ID and ASP.NET membership for a single-sign-on experience.

Refer to Listing 4 (IDLoginView.aspx) and Listing 5 (IDLoginView.aspx.cs) for the following discussion.

After you drag and drop the IDLoginView control onto your Web page, start by setting these two properties: AutomaticallyAssociateAuthentication and PromptOnAssociation. Setting the AutomaticallyAssociateAuthentication property to true instructs the IDLoginView control to associate ASP.NET membership and Windows Live ID when the user is logged in with both identities. IDLoginView calls AssociationManager.AssociateAuthentication passing the ApplicationUserID (Windows Live ID’s unique identifier for the signed-in user at your Web site) and the ASP.NET membership identity. If you chose to set the PromptOnAssociation property to true, the IDLoginView asks the user whether to associate their Windows Live ID with their ASP.NET membership before establishing an association (Figure 6).

![Figure 6: IDLoginView AssociatePromptTemplate (designer view).](https://codemag.com/Article/Image/0804102/Ahuja_Figure 6.tif)

If you haven’t yet, you need to launch the ASP.NET Web Site Administration Tool from Website | ASP.NET Configuration. Please make sure that you make the following changes:

  • Set Authentication type to “From the Internet”. By default, this is not the case. You can access this setting from the Security tab of ASP.NET Web Site Administration, and then clicking “Select the authentication type”.
  • Set up a few users by choosing “Create User”. This will create users for your Web site who will be saved in the ASPNETDB.MDF database in the App_Data folder.

Having set up the users for the Web site, you can test the template switching and association features in IDLoginStatus and IDLoginView, as provided in Listing 4 and Listing 5.

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

The AssociationManager allows a developer to directly query, set, or remove associations for the signed-in user. The Microsoft.Live.ServerControls namespace contains this class. Include a using statement for the Microsoft.Live.ServerControls namespace in your program.

SilverlightStreamingMediaPlayer

You can upload cool videos you created to your Silverlight Streaming account (http://silverlight.live.com) and play them on your Web site with drag-and-drop.

This control allows you to play your videos from a Silverlight Streaming service account. It extends the MediaPlayer control provided by the ASP.NET 3.5 Extensions Preview release.

Developers at design time can provide account credentials for their Silverlight Streaming account and choose the video that their Web page should play. After you drag-and-drop this control onto your Web page, you can specify the video to be played through the “Select Media File” form. This form is accessible through the control’s tasks window or property grid (Figure 7). Developers don’t need to write code to make a connection to Silverlight Streaming servers and choose videos. All this is encapsulated so that you can just specify the credentials and choose a video.

![Figure 7: The SilverlightStreamingMediaPlayer control.](https://codemag.com/Article/Image/0804102/Ahuja_Figure 7.tif)

After you choose the video you want to play, the control saves this video URL in streaming:// format in the control’s MediaSource property. Also, it saves the Account and Key for your Silverlight Streaming account into Web.Config’s <appSettings> section. The following snippet from Web.Config highlights this. I’ve used example values for the AccountID and AccountKey keys:

&lt;appSettings&gt;
  &lt;add key="AccountID" value="MyAccount…" /&gt;
  &lt;add key="AccountKey" value="MyKey…" /&gt;
&lt;/appSettings&gt;

The control’s declaration would look like the following snippet:

&lt;live:SilverlightStreamingMediaPlayer
    ID="SilverlightStreamingMediaPlayer1"    
    runat="server"
    Height="240px"
    Width="320px"
MediaSource      ="streaming:/20709/VideoLibrary
/Assets/Bear.wmv"&gt;
&lt;/live:SilverlightStreamingMediaPlayer&gt;

At run time, the control converts streaming:// URLs to HTTP URLs. You can also set the URL of the video from client side JavaScript with the code snippet below-you need to hook this JavaScript function to an action, say the click of a button:

&lt;script type="text/javascript"&gt;
//set URL for silverlight 
//streaming media player
function SetMediaUrl()
{
    var objSLSMPlayer = 
$find("StreamingMediaPlayer1");
    objSLSMPlayer.set_mediaSource("streaming:
/20709/VideoLibrary/Assets/Lake.wmv");
}
&lt;/script&gt;

Details about the underlying ASP.NET MediaPlayer are available at this link: http://quickstarts.asp.net/3-5-extensions/silverlight/MediaPlayerControl.aspx.

Wrapping Up

I hope the above is helpful in getting you started with the Windows Live Tools. I would love to hear your feedback about Windows Live Tools and how you are going to use it. You can leave your suggestions to improve the feature set or bugs you find as you are using Windows Live Tools at http://dev.live.com/tools.

Listing 1: The OnServerData event handler.

protected void Contacts1_OnServerData(object sender, 
ServerDataEventArgs e)
{
    foreach (Microsoft.Live.ServerControls.Contact objContact in
e.Contacts)
    {
        //Implement custom processing for the contacts received
        CustomProcessingForContact(objContact.FirstName,
                objContact.LastName,
                objContact.PersonalStreet,
                objContact.PersonalState,
                objContact.PersonalPostalCode,
                objContact.PersonalCountry);
    }
}

Listing 2: Default.aspx.

&lt;%@ Page Language="C#" AutoEventWireup="true"
 CodeFile="<a href="http://Default.aspx.cs">Default.aspx.cs</a>" Inherits="_Default" %&gt;
&lt;%@ Register Assembly="Microsoft.Live.ServerControls"
Namespace        ="Microsoft.Live.ServerControls"         TagPrefix        ="live" %&gt;

&lt;html xmlns=<a href="http://www.w3.org/1999/xhtml";>http://www.w3.org/1999/xhtml<;/a>
xmlns:devlive="<a href="http://dev.live.com">http://dev.live.com</a>"&gt;
&lt;head runat="server"&gt;
    &lt;title&gt;CoDe Magazine Article&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form id="frmDemoArticle" runat="server"&gt;
    &lt;asp:ScriptManager ID="scmMgr" runat="server"&gt;
    &lt;/asp:ScriptManager&gt;
    &lt;script type="text/javascript"&gt;
        function Contacts1_OnClientData(sender, args)
        {
          var s = args.contacts.length+ " records\r\n";
          for (var i = 0; i &lt; 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');
        }
    &lt;/script&gt;
    &lt;div&gt;
        &lt;live:Contacts ID="Contacts1" runat="server"
            DataDesired="firstname, lastname, personalstreet,
            personalcity, personalstate, personalcountry,
            personalpostalcode"
            Height="350px" Width="250px" View="List"
            PrivacyStatementURL="~/privacyPolicy.htm"
            OnClientData="Contacts1_OnClientData"
            OnClientCommit="Contacts1_OnClientCommit"
            OnServerData="Contacts1_OnServerData"
            OnServerCommit="Contacts1_OnServerCommit" /&gt;
        &lt;br /&gt;
        &lt;asp:UpdatePanel runat="server"&gt;
            &lt;ContentTemplate&gt;
                &lt;asp:TextBox ID="txtEmail" runat="server"
                    Height="26px" Width="160px"&gt;
                &lt;/asp:TextBox&gt;&amp;nbsp;&amp;nbsp;
               &lt;asp:Button ID="btnAdd" runat="server"
                    Height="26px" Text="Add Contact"
                    onclick="btnAdd_Click" /&gt;
                &lt;br /&gt;&lt;br /&gt;
                &lt;asp:Button ID="btnAddList" runat="server"
                    Text="Add List of Contacts"
                    onclick="btnAddList_Click" /&gt;&amp;nbsp; &amp;nbsp;
                &lt;asp:Button ID="btnDeleteList" runat="server"
                    Text="Delete List of Contacts"
                    onclick="btnDeleteList_Click" /&gt;
            &lt;/ContentTemplate&gt;
            &lt;Triggers&gt;
                &lt;asp:AsyncPostBackTrigger ControlID="btnAdd"
                                            EventName="Click" /&gt;
                &lt;asp:AsyncPostBackTrigger ControlID="btnAddList"
                                            EventName="Click" /&gt;
                &lt;asp:AsyncPostBackTrigger ControlID="btnDeleteList"
                                            EventName="Click" /&gt;
            &lt;/Triggers&gt;
        &lt;/asp:UpdatePanel&gt;
    &lt;/div&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;

Listing 3: Default.aspx.cs.

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using <a href="http://System.Web.UI">System.Web.UI</a>;
using <a href="http://System.Web.UI">System.Web.UI</a>.WebControls;
using <a href="http://System.Web.UI">System.Web.UI</a>.WebControls.WebParts;
using <a href="http://System.Web.UI">System.Web.UI</a>.HtmlControls;
using System.Xml.Linq;
using Microsoft.Live.ServerControls;
using System.Collections.Generic;
using System.Diagnostics;

public partial class _Default : <a href="http://System.Web.UI">System.Web.UI</a>.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}

protected void Contacts1_OnServerData(object sender,
 ServerDataEventArgs e)
{
foreach (Microsoft.Live.ServerControls.Contact objContact in
       e.Contacts)
{
           //Process the contacts received
}
}

//add contact to signed-in user's contacts
protected void btnAdd_Click(object sender, EventArgs e)
{
    List&lt;Contact&gt; objContacts = new List&lt;Contact&gt;();
    Contact objContact = new Contact();
    objContact.EmailPersonal = txtEmail.ToString().Trim();
    objContacts.Add(objContact);

    Contacts1.CreateContacts(objContacts);
    Contacts1.CommitContacts();
}

//add list of contacts to signed-in user's contacts
protected void btnAddList_Click(object sender, EventArgs e)
{
    List&lt;Contact&gt; objContacts = new List&lt;Contact&gt;();
    Contact objContact1 = new Contact();
    objContact1.EmailPersonal = "<a href="mailto://devlivedemo_1@hotmail.com">devlivedemo_1@hotmail.com</a>";
    objContacts.Add(objContact1);

    Contact objContact2 = new Contact();
    objContact2.EmailPersonal = "<a href="mailto://devlivedemo_2@hotmail.com">devlivedemo_2@hotmail.com</a>";
    objContacts.Add(objContact2);

    Contact objContact3 = new Contact();
    objContact3.EmailPersonal = "<a href="mailto://devlivedemo_3@hotmail.com">devlivedemo_3@hotmail.com</a>";
    objContacts.Add(objContact3);

    Contacts1.CreateContacts(objContacts);
    Contacts1.CommitContacts();
}

//delete list of contacts from signed-in user's contacts
protected void btnDeleteList_Click(object sender, EventArgs e)
{
    List&lt;String&gt; Emails = new List&lt;string&gt;();
    Emails.Add("<a href="mailto://devlivedemo_1@hotmail.com">devlivedemo_1@hotmail.com</a>");
    Emails.Add("<a href="mailto://devlivedemo_1@hotmail.com">devlivedemo_1@hotmail.com</a>");
    Emails.Add("<a href="mailto://devlivedemo_1@hotmail.com">devlivedemo_1@hotmail.com</a>");
    Emails.Add("<a href="mailto://devlivedemo_1@hotmail.com">devlivedemo_1@hotmail.com</a>");

    Contacts1.DeleteContacts(Emails);
    Contacts1.CommitContacts();
}

//OnServerCommit event handler
protected void Contacts1_OnServerCommit(object sender,
                      ServerCommitEventArgs e)
{
    if (e.ServerCommitErrors.Count &gt; 0)
    {
        foreach (ServerCommitError objError in 
                  e.ServerCommitErrors)
        {
            Debug.WriteLine(objError.CommitError);
            Debug.WriteLine(objError.Key);
            Debug.WriteLine(objError.CommitActivity);
        }
    }
}
}

Listing 4: IDLoginView.aspx.

&lt;%@ Page Language="C#" AutoEventWireup="true"
    CodeFile="<a href="http://IDLoginView.aspx.cs">IDLoginView.aspx.cs</a>" Inherits="IDLoginView" %&gt;
&lt;%@ Register Assembly="Microsoft.Live.ServerControls"
    Namespace="Microsoft.Live.ServerControls"
    TagPrefix="live" %&gt;

&lt;html xmlns="<a href="http://www.w3.org/1999/xhtml";>http://www.w3.org/1999/xhtml<;/a>"&gt;
&lt;head runat="server"&gt;
    &lt;title&gt;CoDe Magazine Article - IDLoginView&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form id="frmIDLoginView" runat="server"&gt;
    &lt;asp:ScriptManager ID="ScriptManager1" runat="server"&gt;
    &lt;/asp:ScriptManager&gt;
    &lt;div&gt;
        &lt;live:IDLoginStatus ID="IDLoginStatus1" runat="server" /&gt;
        &lt;br /&gt;
        &lt;live:IDLoginView ID="IDLoginView1" runat="server"
            AutomaticallyAssociateAuthentication="True"
            PromptOnAssociation="True"&gt;
            &lt;AnonymousTemplate&gt;
               &lt;asp:Login ID="Login1" runat="server"&gt;&lt;/asp:Login&gt;
         &lt;br /&gt;
               This is anonymous template
            &lt;/AnonymousTemplate&gt;
            &lt;AssociatePromptTemplate&gt;
                Associate your user name for this Website
                with your Windows Live ID?&lt;br&gt;
                &lt;asp:Button runat="server" 
                    CommandName="associate_yes"
                    Text="Yes" Width="55px"
                    ID="IDLoginView1_livepromptyes"&gt;
                &lt;/asp:Button&gt;
                &lt;asp:Button runat="server"
                    CommandName="associate_no"
                    Text="No" Width="55px"
                    ID="IDLoginView1_livepromptno"&gt;
                &lt;/asp:Button&gt;
            &lt;/AssociatePromptTemplate&gt;
            &lt;LoggedInTemplate&gt;
                &lt;asp:LoginStatus ID="LoginStatus1"
                    runat="server" /&gt;
                This template is for ASP.NET logged in users
            &lt;/LoggedInTemplate&gt;
            &lt;LoggedInIDTemplate&gt;
                &lt;asp:Login ID="Login1" runat="server"&gt;
                &lt;/asp:Login&gt;&lt;br /&gt;
                   This template is for Windows Live ID
         signed in users
            &lt;/LoggedInIDTemplate&gt;
            &lt;LoggedInAllTemplate&gt;
                This template is for users logged in both
                Windows Live ID and ASP.NET membership&lt;br /&gt;
                &lt;asp:Button ID="btnRemove" runat="server"
                    Text="Remove Association"
                    onclick="btnRemove_Click" /&gt;
            &lt;/LoggedInAllTemplate&gt;
        &lt;/live:IDLoginView&gt;
    &lt;/div&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;

Listing 5: IDLoginView.aspx.cs.

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using <a href="http://System.Web.UI">System.Web.UI</a>;
using <a href="http://System.Web.UI">System.Web.UI</a>.HtmlControls;
using <a href="http://System.Web.UI">System.Web.UI</a>.WebControls;
using <a href="http://System.Web.UI">System.Web.UI</a>.WebControls.WebParts;
using System.Xml.Linq;
using Microsoft.Live.ServerControls;

public partial class IDLoginView : <a href="http://System.Web.UI">System.Web.UI</a>.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
    }

    //Remove Association
    protected void btnRemove_Click(object sender, EventArgs e)
    {
AssociationManager.RemoveAssociation
(IDLoginStatus1.ApplicationUserID);
    }
}