Exercise 2: Creating the Windows Phone 7 Application

In this exercise, you will create a Windows Phone 7 application to search for SharePoint users and display key profile information.

Task 1 – Beginning the Exercise

In this task, you will open the lab solution in Visual Studio 2010.

  1. Make sure that you have downloaded and installed the items listed in System Requirements above prior to beginning this exercise.
  2. Launch Visual Studio 2010 as administrator and open the lab project by selecting File » Open » Project.
    1. Browse to the WP7.AccBas.Social.sln file located at %TrainingKitPath%\Labs\IntegratingSocialWebServices\Source\Before and select it.
    2. Click Open to open the solution.

Task 2 – Configuring Constants in the Windows Phone 7 Application

In this task, you will configure the constants used in the Windows Phone 7 application to work with your development environment.

  1. In the WP7.AccBas.Social project, in the Utilities folder, open the Constants.cs file.
  2. Change the value for the USER_NAME and USER_PASSWORD constants to represent a Forms Based Authentication user specific to your development environment. For this lab, the user requires read and write permissions.
  3. Change the value for the UPS_SERVICE_URL constant to the URL specific to your development environment.
  4. The following code example demonstrates the value for a SharePoint server named fbawp7.

    C#

    public const string UPS_SERVICE_URL = "https://fbawp7/_vti_bin/authentication.asmx";

  5. Change the value for the AUTHENTICATION_SERVICE_URL constant to the URL specific to your development environment.
  6. The following code example demonstrates the value for a SharePoint server named fbawp7.
  7. public const string AUTHENTICATION_SERVICE_URL = "https://fbawp7/_vti_bin/userprofileservice.asmx”;

Task 3 – Adding a Reference to the SharePoint Search.asmx Web Service

In this task, you will add a reference to the SharePoint search.asmx Web service.

  1. In the Solution Explorer, in the WP7.AccBas.Social project, right click Service References and select Add Service Reference.
  2. In the Addresstextbox enter the URL to the search.asmx for the SharePoint site you are using in this lab.
  3. Example: https://fbawp7/_vti_bin/search.asmx
  4. Click Go.
  5. Once the service is resolved, enter QueryService in the Namespace textbox.
  6. Click OK.

Task 4 – Adding a Reference to the SharePoint Userprofileservice.asmx Web Service

In this task, you will add a reference to the SharePoint lists.asmx Web service.

  1. In the Solution Explorer, in the WP7.AccBas.Social project, right click Service References and select Add Service Reference.
  2. In the Addresstextbox enter the URL to the userprofileservice.asmx for the SharePoint site you are using in this lab.
  3. Example: https://fbawp7/_vti_bin/userprofileservice.asmx
  4. Click Go.
  5. Once the service is resolved, enter UserProfileService in the Namespace textbox.
  6. Click OK.

In this task, you will modify the ServiceReferences.ClientConfig file to support the CookieContainer used with Forms BasedAuthentication. The code used to authenticate to the SharePoint server in this lab uses Forms Based Authentication. Forms Based Authentication requires the use of a CookieContainer. Please see Security With SharePoint And Windows Phone 7 Applications Module for more information about Forms Based Authentication.

  1. In the WP7.AccBas.Social project, open the ServiceReferences.ClientConfig file.
  2. Locate the QueryServiceSoap binding element.
  3. Add the following attribute to the QueryServiceSoap binding element.

    XML

    enableHttpCookieContainer="true"

  4. Locate the UserProfileServiceSoapbinding element.
  5. Add the following attribute to the UserProfileServiceSoap binding element.

    XML

    enableHttpCookieContainer="true"

    The following screenshot shows what the QueryServiceSoap and UserProfileServiceSoap elements looks like after the above code is added.

    Figure 12

    Adding the enableHttpCookieContainer attribute

    Note:
    The following exception will occur if you do not make this change to the ServiceReferences.ClientConfig file.

    Figure 13

    Expected exception when modifying a service with the enableHttpContainer defined

    Note:
    If you change the interface to one or both of the services the application calls and need to update the service reference you will need to remove the XML code above from the ServiceReferences.ClientConfig file then update the service reference. After the service reference update is complete, add the XML code back to the ServiceReferences.ClientConfig file.

Task 6 – Retrieving Matching Users from SharePoint

In this task, you will use the SharePoint search.asmx Web service to return a list of users with a first or last name starting with the search criteria provided by the user.

  1. In the WP7.AccBas.Social project, in the ViewModels folder, open the MainViewModel.cs file.
  2. Add the following code under the //TODO: 4.4.1 comment to define the LoadPeople method:

    C#

    public void LoadPeople() { StringBuilder query = new StringBuilder(); query.Append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>"); query.Append("<QueryPacket xmlns=\"urn:Microsoft.Search.Query\"" + " Revision=\"1000\">"); query.Append("<Query domain=\"QDomain\">"); query.Append("<SupportedFormats>"); query.Append("<Format>urn:Microsoft.Search.Response.Document.Document</Format>"); query.Append("</SupportedFormats>"); query.Append("<Context>"); query.Append("<QueryText language=\"en-US\" type=\"MSSQLFT\">"); query.Append("SELECT "); query.Append("AccountName, "); query.Append("LastName, "); query.Append("FirstName, "); query.Append("Path "); query.Append("FROM SCOPE() "); query.Append("WHERE "); query.Append("(\"DAV:contentclass\" = 'urn:content-class:SPSPeople') "); query.Append(" AND (\"LastName\" LIKE '{0}%')"); query.Append(" OR (\"FirstName\" LIKE '{0}%')"); query.Append("</QueryText>"); query.Append("</Context>"); query.Append("<Range>"); query.Append("<StartAt>1</StartAt>"); query.Append("<Count>150</Count>"); query.Append("</Range>"); query.Append("</Query>"); query.Append("</QueryPacket>"); var proxy = new QueryService.QueryServiceSoapClient(); proxy.CookieContainer = App.CookieJar; proxy.QueryCompleted +=new EventHandler<QueryService.QueryCompletedEventArgs>(proxy_QueryCompleted); proxy.QueryAsync(string.Format(query.ToString(), SearchTerm)); }

    The above code uses a StringBuilder object to build the query that is sent to the search.asmx web service. The WHERE clause limits the search results to only results that have a content type of SPSPeople. The proxy class Visual Studio 2010 generated for the search.asmx service queries SharePoint for matching results.

  3. Add the following code under the //TODO: 4.4.2 comment to define the lists_GetListItemsCompleted method:

    C#

    private void proxy_QueryCompleted(object sender, QueryService.QueryCompletedEventArgs e) { XElement QueryResponse = XElement.Parse(e.Result); XNamespace nsDocument = "urn:Microsoft.Search.Response.Document"; XNamespace nsDocumentDocument = "urn:Microsoft.Search.Response.Document.Document"; var query = from document in QueryResponse.Descendants(nsDocument + "Document") let properties = document.Descendants(nsDocumentDocument + "Property") select new Person { AccountName = properties.Descendants(nsDocumentDocument + "Name") .SingleOrDefault(x => x.Value == "ACCOUNTNAME") .ElementsAfterSelf(nsDocumentDocument + "Value") .SingleOrDefault().Value, LastName = properties.Descendants(nsDocumentDocument + "Name") .SingleOrDefault(x => x.Value == "LASTNAME") != null ? properties.Descendants(nsDocumentDocument + "Name") .SingleOrDefault(x => x.Value == "LASTNAME") .ElementsAfterSelf(nsDocumentDocument + "Value") .SingleOrDefault().Value : "", FirstName = properties.Descendants(nsDocumentDocument + "Name") .SingleOrDefault(x => x.Value == "FIRSTNAME") != null ? properties.Descendants(nsDocumentDocument + "Name") .SingleOrDefault(x => x.Value == "FIRSTNAME") .ElementsAfterSelf(nsDocumentDocument + "Value") .SingleOrDefault().Value : "", }; Deployment.Current.Dispatcher.BeginInvoke(() => { if (People == null) { People = new ObservableCollection<Person>(); } People.Clear(); query.ToList().ForEach(a => People.Add(a)); }); }

    The proxy_QueryCompleted method fires when the call to the search.asmx SharePoint Web service completes. The method uses LINQ to parse the result set and create instances of Person objects. Each Person object is added to the People ObservableCollection. The People observable collection is bound to the MainPage user control in the Windows Phone 7 application. The MainPage user control displays the results of the query.

  4. Save MainViewModel.cs.

Task 7 – Retrieving the User Profile Information from SharePoint

In this task, you will use the SharePoint userprofileservice.asmx Web service to retrieve profile information for a specific user.

  1. In the WP7.AccBas.Social project, in the ViewModels folder, open PersonViewModel.cs file.
  2. Add the following code under the //TODO: 4.4.3 comment to define the RetrieveProfile method:

    C#

    private void RetrieveProfile(Person p) { SPAsmxMessageInspector messageInspector = new SPAsmxMessageInspector(); BasicHttpMessageInspectorBinding binding = new BasicHttpMessageInspectorBinding(messageInspector); EndpointAddress endpoint = new EndpointAddress(Constants.UPS_SERVICE_URL); UserProfileService.UserProfileServiceSoapClient ups = new UserProfileService.UserProfileServiceSoapClient(binding, endpoint); ups.CookieContainer = App.CookieJar; ups.GetUserProfileByNameCompleted += new EventHandler<UserProfileService.GetUserProfileByNameCompletedEventArgs> (ups_GetUserProfileByNameCompleted); ups.GetUserProfileByNameAsync(p.AccountName, p); }

    The above code uses the proxy class Visual Studio 2010 generated for the userprofileservice.asmx service to retrieve a user’s profile information by account name. This example utilizes a custom WCF message inspector to modify the results to be compatible with the Windows Phone 7 Silverlight version.

  3. Add the following code under the //TODO: 4.4.4 comment to define the ups_GetUserProfileByNameCompleted method:

    C#

    void ups_GetUserProfileByNameCompleted(object sender, UserProfileService.GetUserProfileByNameCompletedEventArgs e) { if (e.Error == null) { foreach (UserProfileService.PropertyData propertyData in e.Result) { switch (propertyData.Name) { case "AboutMe": ((Person)e.UserState).AboutMe = propertyData.Values.Count > 0 ? (propertyData.Values[0].Value as string) : String.Empty; break; case "WorkPhone": ((Person)e.UserState).WorkPhone = propertyData.Values.Count > 0 ? (propertyData.Values[0].Value as string) : String.Empty; break; case "CellPhone": ((Person)e.UserState).MobilePhone = propertyData.Values.Count > 0 ? (propertyData.Values[0].Value as string) : String.Empty; break; case "Department": ((Person)e.UserState).Department = propertyData.Values.Count > 0 ? (propertyData.Values[0].Value as string) : String.Empty; break; case "Title": ((Person)e.UserState).Title = propertyData.Values.Count > 0 ? (propertyData.Values[0].Value as string) : String.Empty; break; case "WorkEmail": ((Person)e.UserState).WorkEmail = propertyData.Values.Count > 0 ? (propertyData.Values[0].Value as string) : String.Empty; break; } } } else { throw new Exception(e.Error.Message); } }

    The ups_ GetUserProfileByNameCompleted method fires when the call to the userprofileservice.asmx SharePoint Web service completes. The method updates the passed in Person object with the profile information. The Person object is bound is bound to the PersonView user control in the Windows Phone 7 application. The PersonView user control displays the selected user’s information.

  4. Save PersonViewModel.cs.