Exercise 5: Creating the Windows Phone 7 Application

In this exercise, you will create a Windows Phone 7 application to query the maintenance tasks SharePoint list and the SQL Azure database created in exercise 2. You will also use the PartsServiceEnhanced Windows Azure WCF Service to update data in the PartsInventoryEnhanced SQL Azure database.

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.Cloud.PartsClient.sln file located at %TrainingKitPath%\Labs\IntegratingAzureCloudServicesandData\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.Cloud.PartsClient 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 reader permissions.
  3. Change the value for the AUTHENTICATION_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 AUTHENTICATION_SERVICE_URL = "https://fbawp7/_vti_bin/authentication.asmx";

  5. Change the value for the SQL_AZURE_DATABASE_URL constant to the URL specific to the SQL Azure database created in exercise 2.
  6. The following code example demonstrates the value for a SQL Azure database server named mysqlazuredb. Your database name will be different.

    C#

    public const string SQL_AZURE_DATABASE_URL = "https://odata.sqlazurelabs.com/OData.svc/v0.1/mysqlzauredb/PartsInventoryEnhanced";

Task 3 – Generating the SQL Azure OData Proxy Class

In this task, you will use the datasvcutil.exe command line program to generate a proxy class for the PartsInventory SQL Azure database.

  1. Open a command prompt.
  2. Change to the %System%\Microsoft.NET\Framework\v4.0.30319 directory.
  3. Execute the following command. Replace the <SQL Azure Database Server Name> token with the name of the SQL Azure database server created in exercise 2.

    Command

    Datasvcutil.exe /uri:https://odata.sqlazurelabs.com/OData.svc/v0.1/<SQL Azure Database Server Name>/PartsInventoryEnhanced /out:c:\PartsInventoryEnhanced.cs /Version:2.0 /DataServiceCollection

    Figure 14

    Create proxy for service

  4. Copy the c:\PatrsInventoryEnhanced.cs file to the %TrainingKitPath%\Labs\Azure\ServicesAndData\Source\Before\WP7.Cloud.PartsClient\OData directory.
  5. In the Solution Explorer, right click the OData folder, select Add, and then select Existing Item.
  6. Browse to the %TrainingKitPath%\Labs\IntegratingAzureCloudServicesandData\Source\Before\WP7.Cloud.PartsClient\OData directory.
  7. Select the PartsInventoryEnhanced.cs file.
  8. Open the PartsInventoryEnhanced.cs file.
  9. Change the namespace to WP7.Cloud.PartsClient.

    Figure 15

    Change the namespace

  10. Save PartsInventoryEnhanced.cs.

Task 4 – Retrieving Maintenance Requests from SharePoint

In this task, you will use the SharePoint lists.asmx Web service to return maintenance requests from the SharePoint list.

  1. In the WP7.Cloud.PartsClient project, in the ViewModels folder, open the MainViewModel.cs file.
  2. Add the following code under the //TODO: 8.3.1 comment to define the LoadMaintenanceTasks method:

    C#

    public void LoadMaintenanceTasks() { XElement viewFields = new XElement("ViewFields", new XElement("FieldRef", new XAttribute("Name", "Title")), new XElement("FieldRef", new XAttribute("Name", "Body")), new XElement("FieldRef", new XAttribute("Name", "Make")), new XElement("FieldRef", new XAttribute("Name", "Model"))); WP7.Cloud.PartsClient.SPListsService.ListsSoapClient lists = new WP7.Cloud.PartsClient.SPListsService.ListsSoapClient(); lists.CookieContainer = App.CookieJar; lists.GetListItemsCompleted += new EventHandler<WP7.Cloud.PartsClient.SPListsService. GetListItemsCompletedEventArgs>(lists_GetListItemsCompleted); lists.GetListItemsAsync(Constants.SHAREPOINT_LIST_NAME, string.Empty, null, viewFields, null, null, null); }

    The above code uses the proxy class Visual Studio 2010 generated for the lists.asmx service to query the Maintenance Tasks SharePoint list.

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

    C#

    void lists_GetListItemsCompleted(object sender, WP7.Cloud.PartsClient.SPListsService.GetListItemsCompletedEventArgs e) { IEnumerable<XElement> rows = e.Result.Descendants(XName.Get("row", "#RowsetSchema")); IEnumerable<SPMaintenanceTask> maintenanceTasks = from element in rows select new SPMaintenanceTask { Title = (string)element.Attribute("ows_Title"), Body = Utils.HtmlToText((string)element.Attribute("ows_Body")), Make = (string)element.Attribute("ows_Make"), Model = (string)element.Attribute("ows_Model") }; Deployment.Current.Dispatcher.BeginInvoke(() => { if (MaintenanceTasks == null) { MaintenanceTasks = new ObservableCollection<SPMaintenanceTask>(); } MaintenanceTasks.Clear(); maintenanceTasks.ToList().ForEach(a => MaintenanceTasks.Add(a)); }); }

    The lists_GetListItemsCompleted method fires when the call to the lists.asmx SharePoint Web service completes. The method parses the result set, creates an instance of the SPMaintenanceTask that represents each maintenance task in the SharePoint list, and adds the SPMaintenanceTask instances to the MaintenanceTasks observable collection. The MaintenanceTasks observable collection is bound to the MainPage user control in the Windows Phone 7 application. The MainPage user control displays the maintenance requests retrieved from the SharePoint list.

  4. Save MainViewModel.cs.

Task 5 – Adding a Reference to the Windows Azure WCF Service

In this task, you will add a reference to the PartsServiceEnhanced Windows Azure WCF Service created in Exercise 2

  1. In the Solution Explorer, in the WP7.Parts.Client project, right click Service References and select Add Service Reference.
  2. In the Address textbox enter the URL to the local running instance of the PartsServiceEnhanced Windows Azure Service.
  3. Example: https://127.0.0.1:82/PartService.svc?wsdl
  4. Click Go.
  5. Once the service is resolved, enter PartsService in the Namespace textbox.
  6. Click OK.

Task 6– Retrieving Replacement Part Inventory Levels from SQL Azure

In this task, you will retrieve the replacement part inventory levels from the PartsInventoryEnhanced SQL Azure database.

  1. In the WP7.Cloud.PartsClient project, in the ViewModels folder, open the MaintenanceTaskViewModel.cs file.
  2. Add the following code under the //TODO: 8.3.3 comment to define the CheckInternalInventory method:

    C#

    public void CheckInternalInventory(string make, string model) { context = new PartsInventoryEnhanced(new Uri(Constants.SQL_AZURE_DATABASE_URL)); Uri requestUri = new Uri(context.BaseUri.OriginalString + "/Parts()?$filter=(Make eq '" + make + "') and (Model eq '" + model + "')"); context.BeginExecute<Part>(requestUri, CheckInternalInventoryCallback, null); }

    The above code uses the proxy class Visual Studio 2010 generated for the PartsInventoryEnhanced SQL Azure database to return the replacement part inventory levels from the PartsInventoryEnhanced SQL Azure database. The OData query uses the $filter querystring parameter to return only the rows of data that match the make and model of the part associated with the selected maintenance request.

  3. Add the following code under the //TODO: 8.3.4 comment to define the CheckInternalInventoryCallback method:

    C#

    private void CheckInternalInventoryCallback(IAsyncResult asyncResult) { IEnumerable<Part> results; results = context.EndExecute<Part>(asyncResult).ToList() as IEnumerable<Part>; Deployment.Current.Dispatcher.BeginInvoke(() => { if (Parts == null) { Parts = new ObservableCollection<Part>(); } Parts.Clear(); foreach (Part part in results) { Parts.Add(part); } PartCount = Parts.Count().ToString(); }); }

    The CheckInternalInventoryCallback method fires when the call to the OData query to the PartsInventoryEnhanced SQL Azure database completes. First, the method takes the result set, and creates an IEnumerable list of type Part. The Part class is defined in the OData proxy class. Then a new instance of the Parts observable collection is created and each Part returned from the result set is added to the observable collection. The Parts observable collection is bound to the MaintenanceTaskView user control in the Windows Phone 7 application. This collection is used to display the list of warehouses that currently stock the part and how many parts are available in each warehouse.

    Then, the CheckInternalInventoryCallback method sets the PartCount property equal to the number of items returned by the query. The PartCount property is bound to the MaintenanceTaskView user control in the Windows Phone 7 application. This property is used to display the number of warehouses that currently stock the part.

    The MaintenanceTaskView user control displays detailed information for a maintenance request selected in the MainPage user control. The detailed information includes the metadata about a give maintenance request from the SharePoint list, as well as the replacement part inventory level data from the PartsInventoryEnhanced SQL Azure database.

  4. Save MaintenanceTaskViewModel.cs.

Task 7 – Updating Replacement Part Order Status in SQL Azure

In this task, you will use the PartsServiceEnhanced Windows Azure WCF Service to update data in the PartsInventoryEnhanced SQL Azure database.

In the WP7.Cloud.PartsClient project, in the ViewModels folder, open the MaintenanceTaskViewModel.cs file.

  1. Add the following code under the //TODO: 8.3.5 comment to define the UpdateInventoryRecord method:

    C#

    public void UpdateInventoryRecord(int ID) { WP7.Cloud.PartsClient.PartsService.PartServiceClient partsService = new PartsService.PartServiceClient(); partsService.UpdateOrderStatusAsync(ID, true); partsService.UpdateOrderStatusCompleted += new EventHandler<PartsService.UpdateOrderStatusCompletedEventArgs> (partsService_UpdateOrderStatusCompleted); }

    The above code uses the proxy class Visual Studio 2010 generated for the PartsInventoryEnhanced Windows Azure WCF Service update data in the PartsInventoryEnhanced SQL Azure database.

  2. Add the following code under the //TODO: 8.3.6 comment to define the partsService_UpdateOrderStatusCompleted method:

    C#

    void partsService_UpdateOrderStatusCompleted(object sender, PartsService.UpdateOrderStatusCompletedEventArgs e) { CheckInternalInventory(this.dataModel.Make, this.dataModel.Model); }

    The partsService_UpdateOrderStatusCompleted method fires when the call to the update the PartsInventoryEnhanced SQL Azure database completes. It calls the CheckInternalInventory method to refresh the UI.

  3. Save MaintenanceTaskViewModel.cs.

In this task, you will modify the web.config 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 Module 6 for more information about Forms Based Authentication.

  1. In the WP7.Cloud.PartsClient project, in the ViewModels folder, open the ServiceReferences.ClientConfig file.
  2. Locate the ListsSoap binding element.
  3. Add the following attribute to the ListsSoap binding element.

    XML

    enableHttpCookieContainer="true"

    The following screenshot shows what the ListSoap binding element looks like after the above code is added.

    Figure 16

    Enable cookie support

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

    Figure 17

    Invalid operation exception

    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.