az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will...

48
Hands-On Lab Windows Phone 7 & The Cloud Lab version: 1.0.0 Last updated: 7/9/2022 Page | 1

Transcript of az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will...

Page 1: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

Hands-On LabWindows Phone 7 & The CloudLab version: 1.0.0

Last updated: 5/24/2023

Page | 1

Page 2: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

CONTENTS

OVERVIEW................................................................................................................................................. 3

EXERCISE 1: CONNECTING WINDOWS PHONE 7 WITH WCF DATA SERVICES................................8Task 1 – Exposing an Entity Framework Model Using WCF Data Services...........................................8

Task 2 – Creating WP7 Client Consuming WCF Data Services............................................................14

SUMMARY................................................................................................................................................ 44

Page | 2

Page 3: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

Overview

This hands-on lab introduces you to the tools and the steps required to build a small Silverlight Windows Phone 7 application that consumes a WCF Data Services from an application hosted in Windows Azure.

WCF Data Services enables you to expose and consume data from different devices and infrastructures leveraging the Open Data Protocol (OData). OData is a protocol that allows you to expose your data as resources that are addressable by URIs. This enables you to use the semantics of representational state transfer (REST) for accessing the exposed data. The standard HTTP verbs of GET, PUT, POST, and DELETE are supported by it.

Page | 3

Page 4: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

In this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its entity model through a WCF Data Service, which will then be consumed by the Windows Phone 7 Client. MyTODO is a Microsoft Developer & Platform Evangelism sample application built on Windows Azure to manage and share simple lists (e.g. tasks to complete, favorite movies, books you enjoyed, etc.).

If you want to explore a complete version of the myTODO sample application, you can download it from http://code.msdn.microsoft.com/mytodo.

Objectives

In this hands-on lab, you will learn how to:

Expose an Entity Framework model using WCF Data Services

Create a Windows Phone 7 Client that consumes WCF Data Services

Page | 4

Page 5: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

Prerequisites

The following is required to complete this hands-on lab:

IIS 7 (with ASP.NET, WCF HTTP Activation)

Microsoft .NET Framework 4.0

Microsoft Visual Studio 2010

Windows Azure Tools for Microsoft Visual Studio 1.6

Windows Phone 7 SDK

Setup

For convenience, much of the code used in this hands-on lab is available as Visual Studio code snippets. To check the prerequisites of the lab and install the code snippets:

Note: Make sure you have checked all the dependencies for this lab before running the setup.

1. In order to allow the solution to connect with the database using SQL Server credentials, open SQL Server Management Studio and connect to the local SQL Server (i.e. .\sqlexpress).

2. Right click the server node and select Properties.

3. Select Security and make sure SQL Server and Windows Authentication mode is selected.

Page | 5

Page 6: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

Figure 1SQL Server Properties - Security

4. Click OK.

5. Restart the SQL Server instance to allow the previous configuration change to take effect.

Page | 6

Page 7: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

Figure 2Restart SQL Server

6. Open a Windows Explorer window and browse to the lab’s Source folder.

7. Double-click the Setup.cmd file in this folder to launch the set up process that will configure your environment and install the Visual Studio code snippets for this lab.

8. If the User Account Control dialog is shown, confirm the action to proceed.

Using the Code Snippets

Throughout the lab document, you will be instructed to insert code blocks. For your convenience, most of that code is provided as Visual Studio Code Snippets, which you can use from within Visual Studio 2010 to avoid having to add it manually.

If you are not familiar with the Visual Studio Code Snippets, and want to learn how to use them, you can refer to the Setup.docx document in the Assets folder of the training kit, which contains a section describing how to use them.

Exercises

This hands-on lab includes the following exercises:

1. Connecting Windows Phone 7 with WCF Data Services.

Page | 7

Page 8: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

Estimated time to complete this lab: 30 minutes.

Note: When you first start Visual Studio, you must select one of the predefined settings collections. Every predefined collection is designed to match a particular development style and determines window layouts, editor behavior, IntelliSense code snippets, and dialog box options. The procedures in this lab describe the actions necessary to accomplish a given task in Visual Studio when using the General Development Settings collection. If you choose a different settings collection for your development environment, there may be differences in these procedures that you need to take into account.

Exercise 1: Connecting Windows Phone 7 with WCF Data Services

In this exercise, you will start with a simplified version of MyTODO and go through the steps of adding a WCF Data Service to expose its entity model, and then create a Windows Phone 7 client application that consumes it.

Task 1 – Exposing an Entity Framework Model Using WCF Data Services

In this task, you will create a WCF Data Service to expose MyTODO’s entity model and host it in the Cloud.

1. Open Visual Studio 2010 as an administrator. Go to the File | Open | Project menu and select Begin.sln located in the Source\Ex01-Connectivity\Begin folder of the lab.

2. Press F5 to run the application. Log on to the application and try the different options: creating a task list, adding tasks, marking a task as completed.

3. Close the browser and go back to Visual Studio.

4. Add a WCF Data Service class named MyTodoDataService to the MyTodo.Web project.

Page | 8

Page 9: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

Figure 3Adding a WCF Data Service

5. In the newly created MyTodoDataService class, insert the following namespace directives following the existing directives at the top of the file.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 UsingDataService - C#)

C#

using System.Diagnostics;using System.Linq.Expressions;using System.Security.Principal;using System.ServiceModel;using Microsoft.Samples.MyTodo.Web.Models;using System.Web.Security;using System.ServiceModel.Activation;

6. In the class definition, replace the placeholder labeled /* TODO: put your data source class name here */ with the name MyTodoEntities.

7. Add the following attributes to MyTodoDataService class.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 Attributes - C#)

C#

[ServiceBehavior(IncludeExceptionDetailInFaults = true)][AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]

Page | 9

Page 10: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

8. Locate the InitializeService method, and replace its code with the following, this will expose the TaskLists and Task entities to everyone consuming the service, later on this task, we will add the logic to only return the public Tasks.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 InitializeService - C#)

C#

config.SetEntitySetAccessRule("TaskLists", EntitySetRights.All);config.SetEntitySetAccessRule("Tasks", EntitySetRights.All);config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);config.UseVerboseErrors = true;

Figure 4WCF Data Service Definition

9. Add a UserIdentity property, which will be used to identify the user that is consuming the service and to validate if he has access to the resources, or not.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 UserIdentity - C#)

C#

private IIdentity UserIdentity{ get { string ticketValue = null; var cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName]; if (cookie != null) { // from cookie ticketValue = cookie.Value; }

Page | 10

Page 11: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

else if (HttpContext.Current.Request.Headers["AuthToken"] != null) { // from http header ticketValue = HttpContext.Current.Request.Headers["AuthToken"]; } if (!string.IsNullOrEmpty(ticketValue)) { try { var ticket = FormsAuthentication.Decrypt(ticketValue); if (ticket != null) { return new FormsIdentity(ticket); } } catch { } }

return null; }}

10. Add the code below to the service definition; these methods contain the logic to hide those entities which are not public or owned by the user consuming the service.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 ListViewEventHandlers - C#)

C#

[WebGet]public IQueryable<TaskList> GetPublicLists(){ return this.CurrentDataSource.TaskLists .Where(o => o.IsPublic == 1) .OrderBy(o => o.Name);}

[QueryInterceptor("Tasks")]public Expression<Func<Task, bool>> QueryTasks(){ if (this.UserIdentity == null) { return c => c.TaskList.IsPublic == 1; } else {

Page | 11

Page 12: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

return c => c.TaskList.UserName.Equals(this.UserIdentity.Name, StringComparison.OrdinalIgnoreCase); }}

[QueryInterceptor("TaskLists")]public Expression<Func<TaskList, bool>> QueryTaskLists(){ if (this.UserIdentity == null) { return c => c.IsPublic == 1; } else { return c => c.UserName.Equals(this.UserIdentity.Name, StringComparison.OrdinalIgnoreCase); }}

11. In order to verify the correct implementation of the WCF Data service, press F5 to run the application.

Page | 12

Page 13: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

Figure 5Running Application

12. In Internet Explorer, append /MyTodoDataService.svc to the URL, and press ENTER. The address should look like http://127.0.0.1:{port}/MyTodoDataService.svc.

Page | 13

Page 14: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

Figure 6Running Application

Task 2 – Creating WP7 Client Consuming WCF Data Services

In this task, you will go through the steps of creating a Windows Phone 7 client to consume the WCF Data Service created in the previous task.

1. Add New Project using the Silverlight for Windows Phone – Windows Phone Application template, named MyTodo.Phone.Online

2. Add reference to the OData Client Library for WP7 (System.Data.Services.Client) located in the folder Assets\libs.

3. Remove the file MainPage.xaml located into the root of the project since you will not need it.

4. Add New Folder named Model, and create a new class named TasksList inside it.

5. Replace the class definition with the following.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 TaskList - C#)

C#

namespace MyTodo.Phone.Online.Models{ using System; using System.Collections.ObjectModel; using System.Data.Services.Common;

Page | 14

Page 15: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

[DataServiceEntity] [DataServiceKey("Id")] public class TaskList { public TaskList() { this.Tasks = new Collection<Task>(); }

public Guid Id { get; set; }

public string UserName { get; set; }

public string Name { get; set; }

public byte IsPublic { get; set; }

public Collection<Task> Tasks { get; set; } }}

6. Inside the Models folder, add another class, named Task, and replace its implementation with the following.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 Task - C#)

C#

namespace MyTodo.Phone.Online.Models{ using System; using System.Data.Services.Common;

[DataServiceEntity] [DataServiceKey("Id")] public class Task { public Guid Id { get; set; }

public string UserName { get; set; }

public TaskList TaskList { get; set; }

public string Name { get; set; }

public string Description { get; set; }

public int Status { get; set; }

Page | 15

Page 16: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

public DateTime StartDate { get; set; }

public DateTime DueDate { get; set; }

public DateTime TimestampUpdate { get; set; } }}

7. Add a new folder named Services in the Project’s root folder.

8. Inside it, add an interface named ITodoService, and replace its definition with the following

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 ITodoService - C#)

C#

using System;using System.Collections.Generic;using MyTodo.Phone.Online.Models;

namespace MyTodo.Phone.Online.Services{ public interface ITodoService { event EventHandler<ServiceExceptionArgs> ServiceException;

void GetLists(Action<IEnumerable<TaskList>> callback); void GetListAndTasks(Guid listId, Action<TaskList> callback); void AddList(TaskList list, Action<TaskList> callback); void AddTask(TaskList list, Task task, Action<Task> callback); void DeleteTask(Task task, Action<Task> callback); void UpdateTask(Task task, Action<Task> callback); }

public class ServiceExceptionArgs : EventArgs { public Exception Exception { get; set; } }}

9. Add a class named OnlineTodoService in the Services folder, which will implement the ITodoService interface and contain the logic required to consume the OData service.

10. Add the following namespace directives below the ones added by the class template.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 OnlineTodoServiceNamespaces - C#)

C#Page | 16

Page 17: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

...using System.Collections.Generic;using System.Data.Services.Client;using System.Diagnostics;using System.Linq;using MyTodo.Phone.Online.Infrastructure;using MyTodo.Phone.Online.Models;

11. Implement the ITodoService interface, to do this, type : ITodoService behind the OnlineTodoService class name, click on the contextual menu, and select Implement Interface ITodoService.

Figure 7Implement ITodoService Interface

12. Add the following code to the beginning of the class definition, this code contains the logic to create the Context that will be used to consume the WCF Data Service, adding the AuthenticationToken to each requests.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 OnlineTodoServiceDeclarations- C#)

C#

public class OnlineTodoService : ITodoService { private readonly Uri serviceUri;

public OnlineTodoService(Uri serviceUri) { this.serviceUri = serviceUri; }

private DataServiceContext GetContext() { var dataService = new DataServiceContext(serviceUri); dataService.MergeOption = MergeOption.OverwriteChanges; dataService.SendingRequest += (sender, args) => { if (string.IsNullOrEmpty(App.AuthenticationToken))

Page | 17

Page 18: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

{ throw new ArgumentNullException("AuthenticationToken", "The AuthenticationToken is not set."); }

args.RequestHeaders["AuthToken"] = App.AuthenticationToken; };

return dataService; }...

When using the implement interface option, all methods where added but with no actual implementation.

13. Replace the auto-generated code of GetLists method with the code required to invoke the WCF Data Service.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 OnlineTodoServiceGetLists - C#)

C#

public event EventHandler<ServiceExceptionArgs> ServiceException;

... public void GetLists(Action<IEnumerable<TaskList>> callback) { var requestUri = new Uri(string.Format("{0}TaskLists?$orderby='Name asc'&$expand=Tasks", serviceUri), UriKind.Absolute); var ctx = this.GetContext();

ctx.BeginExecute<TaskList>( requestUri, delegate(IAsyncResult asyncResult) { try { var result = ctx.EndExecute<TaskList>(asyncResult).ToArray(); Deployment.Current.Dispatcher.BeginInvoke(() => { callback(result); }); } catch (Exception ex) { Debug.WriteLine(ex.ToString()); Deployment.Current.Dispatcher.BeginInvoke(() => { if (this.ServiceException != null)

Page | 18

Page 19: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

{ this.ServiceException(this, new ServiceExceptionArgs { Exception = ex }); } }); } }, null); }...

Note: As you can see, the code generates the URI that asks for all the TaskLists to the service, ordered by Name (ascendant) and expanding its Tasks. For more information on the URI conventions used for OData services you can visit http://www.odata.org/developers/protocols/uri-conventions

14. Replace the auto-generated code of AddList method with the code required to invoke the WCF Data Service.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 OnlineTodoServiceAddList - C#)

C#

public void AddList(TaskList list, Action<TaskList> callback) { list.UserName = string.Empty; var dataService = this.GetContext(); dataService.AddObject("TaskLists", list); dataService.BeginSaveChanges( delegate(IAsyncResult asyncResult) { try { var response = dataService.EndSaveChanges(asyncResult).First(); Deployment.Current.Dispatcher.BeginInvoke(() => { callback(asyncResult.AsyncState as TaskList); }); } catch (Exception ex) { Debug.WriteLine(ex.ToString()); Deployment.Current.Dispatcher.BeginInvoke(() => { if (this.ServiceException != null) {

Page | 19

Page 20: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

this.ServiceException(this, new ServiceExceptionArgs { Exception = ex }); } }); } }, list ); }

15. Add the IAuthentication and the Authentication files located in the Assets\Services folder into the Services folder of your WP7 project. These files will handle the authentication logic, which is not in the scope of this exercise.

16. Add a service reference to the Authentication service. To do this, right-click on the WP7 project and select Add service reference. Click on Discover, and wait until the AuthenticationService.svc appears. Select it and make sure that the Address is http://localhost:{port}/AuthenticationService.svc.

17. Type Services as its namespace and click OK to add the reference.

Page | 20

Page 21: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

Figure 8Add Authentication service reference

18. The next step is to add the ServiceFactory, which will contain the logic for building the services required by the application. To do this, add a new folder named Infrastructure to the root of the WP7 project.

19. Inside it, add a new class named ServiceFactory.

20. Replace the class definition with the following.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 ServiceFactory - C#)

C#

using System;using System.Diagnostics;using System.Windows;using MyTodo.Phone.Online.Services;

namespace MyTodo.Phone.Online.Infrastructure

Page | 21

Page 22: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

{ public static class ServiceFactory { private static IAuthentication authentication; private static ITodoService todoService;

public static Uri GetApplicationUri() { return new Uri(Application.Current.Resources["ApplicationUrlString"].ToString(), UriKind.Absolute); }

public static Uri GetTodoServiceUri() { return new Uri(GetApplicationUri() + "MyTodoDataService.svc/", UriKind.Absolute); }

public static IAuthentication GetAuthentication() { if (authentication == null) { authentication = new Authentication(GetApplicationUri() + "AuthenticationService.svc");

authentication.AuthenticationException += (sender, args) => { if (args.WrongCredentials) { App.UserName = null; App.AuthenticationToken = null; } };

authentication.AuthenticationSuccess += (sender, args) => { App.UserName = args.UserName; App.AuthenticationToken = args.AuthenticationToken; }; }

return authentication; }

public static ITodoService GetTodoService()Page | 22

Page 23: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

{ if (todoService == null) { todoService = new OnlineTodoService(GetTodoServiceUri()); todoService.ServiceException += (sender, e) => { Debug.WriteLine(e.Exception.ToString()); MessageBox.Show(e.Exception.ToString(), "Service Error", MessageBoxButton.OK); }; }

return todoService; }

}}

Up to this point, you have added all the logic required to handle the Authentication and Interaction with the WCF Data Service. Your Project should look as the following:

Figure 9Windows Phone 7 Project

Now, you will proceed by adding the Views, ViewModels and all resources required by them in order to display the TaskLists and their tasks.

21. Open the App.xaml file located in the root of the project, and add the following code into the Application:Resources tag.

Page | 23

Page 24: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 ApplicationResources)

XAML

... <!--Application Resources--> <Application.Resources> <system:String x:Key="ApplicationNameString">MY TODO</system:String> <system:String x:Key="ApplicationUrlString">http://localhost:81/</system:String> </Application.Resources>...

22. Also, add the System namespace into the Application tag.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 SystemReference)

XAML

<Application x:Class="Microsoft.Samples.MyTodo.Phone.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone">

23. Press F7 to switch to the App.xaml code behind, and add the following fields at the beginning of the class. These fields will be used to store the user context of the application.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 UserContextInformation)

C#

public partial class App : Application {

//User Context public static string UserName; public static string AuthenticationToken;...

24. Create a new folder named Views, in your WP7 Project. Inside it, add a new Windows Phone Portrait Page named ListsView.

Page | 24

Page 25: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

Figure 10Add new Windows Phone Portrait Page

25. If not already opened, open the ListView.xaml page you have just created and add the converters namespace into the phone:PhoneApplicationPage tag. You will add all the required converters later on this task.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 ConvertersNamespace)

XAML

xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:converters="clr-namespace:MyTodo.Phone.Online.Converters" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="PortraitOrLandscape" Orientation="Portrait" mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480" shell:SystemTray.IsVisible="True">...

Page | 25

Page 26: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

26. Replace the code inside the phone:PhoneApplicationPage tag with the following.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 PhoneApplicationPage)

XAML

shell:SystemTray.IsVisible="True">

<phone:PhoneApplicationPage.Resources> <converters:VisibilityConverter x:Key="VisibilityConverter" /> <Storyboard x:Name="PageTransitionReset"> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)"> <EasingDoubleKeyFrame KeyTime="00:00:00" Value="90"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.CenterOfRotationX)"> <EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/> </DoubleAnimationUsingKeyFrames> </Storyboard> <Storyboard x:Name="PageTransitionIn"> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)"> <EasingDoubleKeyFrame KeyTime="00:00:00" Value="90"/> <EasingDoubleKeyFrame KeyTime="00:00:00.3" Value="0"> <EasingDoubleKeyFrame.EasingFunction> <CircleEase EasingMode="EaseIn"/> </EasingDoubleKeyFrame.EasingFunction> </EasingDoubleKeyFrame> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.CenterOfRotationX)"> <EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/> <EasingDoubleKeyFrame KeyTime="00:00:00.3" Value="0"> <EasingDoubleKeyFrame.EasingFunction> <CircleEase EasingMode="EaseIn"/> </EasingDoubleKeyFrame.EasingFunction> </EasingDoubleKeyFrame> </DoubleAnimationUsingKeyFrames> </Storyboard> <Storyboard x:Name="PageTransitionOut"> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)"> <EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/> <EasingDoubleKeyFrame KeyTime="00:00:00.3" Value="90">

Page | 26

Page 27: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

<EasingDoubleKeyFrame.EasingFunction> <CircleEase EasingMode="EaseIn"/> </EasingDoubleKeyFrame.EasingFunction> </EasingDoubleKeyFrame> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.CenterOfRotationX)"> <EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/> <EasingDoubleKeyFrame KeyTime="00:00:00.3" Value="0"> <EasingDoubleKeyFrame.EasingFunction> <CircleEase EasingMode="EaseIn"/> </EasingDoubleKeyFrame.EasingFunction> </EasingDoubleKeyFrame> </DoubleAnimationUsingKeyFrames> </Storyboard> </phone:PhoneApplicationPage.Resources> <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.Projection> <PlaneProjection /> </Grid.Projection> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions>

<!--TitlePanel contains the name of the application and page title--> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="24,24,0,12"> <TextBlock x:Name="ApplicationTitle" Text="{StaticResource ApplicationNameString}" Style="{StaticResource PhoneTextNormalStyle}" Margin="0" /> <TextBlock x:Name="PageTitle" Text="my lists" Margin="-3,-8,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel>

<Grid Grid.Row="1"> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Border Margin="12,24,0,12"> <Grid Visibility="{Binding IsBusy, ConverterParameter=False, Converter={StaticResource VisibilityConverter}}"> <TextBlock Visibility="{Binding HasItems, ConverterParameter=False, Converter={StaticResource VisibilityConverter}}" Text="You don't have any lists." Style="{StaticResource PhoneTextSubtleStyle}"/>

Page | 27

Page 28: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

<ListBox Visibility="{Binding HasItems, Converter={StaticResource VisibilityConverter}}" x:Name="ItemsListBox" ItemsSource="{Binding Items}"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" Margin="0,0,0,30"> <Image x:Name="ItemImage" Source="/Microsoft.Samples.MyTodo.Phone;component/Resources/Images/ArrowImg.png" Height="43" Width="43" VerticalAlignment="Top" Margin="10,0,20,0"/> <StackPanel> <TextBlock x:Name="ItemText" Text="{Binding Name}" Margin="-2,-13,0,0" Style="{StaticResource PhoneTextExtraLargeStyle}" TextWrapping="Wrap" Width="395" /> <StackPanel Orientation="Horizontal" Margin="0,-6,0,3"> <Image Source="/Microsoft.Samples.MyTodo.Phone;component/Resources/Images/PublicImg.png" Height="30" Width="30" Visibility="{Binding IsPublic, Converter={StaticResource VisibilityConverter}, ConverterParameter=1}" /> <TextBlock Text="Public" Style="{StaticResource PhoneTextSubtleStyle}" Margin="0" Visibility="{Binding IsPublic, Converter={StaticResource VisibilityConverter}, ConverterParameter=1}" />

<Image Source="/Microsoft.Samples.MyTodo.Phone;component/Resources/Images/PublicImg.png" Height="30" Width="30" Opacity="0.35" Visibility="{Binding IsPublic, Converter={StaticResource VisibilityConverter},ConverterParameter=0}" /> <TextBlock Text="Private" Style="{StaticResource PhoneTextSubtleStyle}" Margin="0" Visibility="{Binding IsPublic, Converter={StaticResource VisibilityConverter},ConverterParameter=0}" />

<TextBlock Text=" | Tasks: " Style="{StaticResource PhoneTextSubtleStyle}" Margin="0" /> <TextBlock Text="{Binding Tasks.Count}" Style="{StaticResource PhoneTextSubtleStyle}" Margin="0" /> </StackPanel> </StackPanel> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </Border>

Page | 28

Page 29: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

<TextBlock Margin="12,24,0,12" Visibility="{Binding IsBusy, Converter={StaticResource VisibilityConverter}}" Text="Loading..." Style="{StaticResource PhoneTextSubtleStyle}"/>

<Border Grid.Row="1"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <TextBox x:Name="NewListTextBox" Text="{Binding NewListName, Mode=TwoWay}" HorizontalAlignment="Stretch" VerticalAlignment="Center" KeyUp="NewListTextBox_KeyUp" GotFocus="NewListTextBox_GotFocus" LostFocus="NewListTextBox_LostFocus" /> <Button x:Name="NewListButton" Content="+" Grid.Column="1" Click="NewListButton_Click" VerticalAlignment="Stretch" /> </Grid> </Border> </Grid> </Grid>

</phone:PhoneApplicationPage>

Note: The code you have just added contains the UI structure of the page and its bindings to the ViewModel which you will add later. The page will simply display a list of tasks.

27. Press F7 to switch to the ListsView’s code behind.

28. Replace the default namespace definition with the ones shown below.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 ListViewNamespaces - C#)

C#

using System; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using Microsoft.Phone.Controls; using MyTodo.Phone.Online.ViewModels; using MyTodo.Phone.Online.Models;

29. Add the following code into the constructor, below the call to the InitializeComponent method, to create the appropriate ViewModel.

Page | 29

Page 30: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

Note: Do not worry if your solution does not build at this point, you will add the missing ViewModel later on this task.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 ListViewInitializeComponent - C#)

C#

public ListsView() { InitializeComponent();

this.PageTransitionReset.Begin(); this.Loaded += (sender, args) => { this.PageTransitionIn.Begin(); this.ViewModel.Reload(); };

this.PageTransitionOut.Completed += (sender, args) => { if (this.selectedItem != null) { // navigate NavigationService.Navigate(new Uri("/Views/TasksView.xaml?listId=" + this.selectedItem.Id, UriKind.Relative)); } else { // back NavigationService.GoBack(); } };

this.ViewModel = new ListsViewModel(); this.ViewModel.IsBusy = true; }

30. Add the selectedItem field above the class constructor.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 TaskListSelectedItem - C#)

C#

public partial class ListsView : PhoneApplicationPage { private TaskList selectedItem;

Page | 30

Page 31: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

public ListsView() {...

31. Add the following code below the constructor, this code will handle the user interaction in the page.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 ListsViewEventHandlers - C#)

C#

this.ViewModel = new ListsViewModel(); this.ViewModel.IsBusy = true; }

public ListsViewModel ViewModel { get { return this.DataContext as ListsViewModel; } set { this.DataContext = value; } }

private void ItemsListBox_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { this.selectedItem = ((ListBox)sender).SelectedItem as TaskList; if (this.selectedItem != null) { this.PageTransitionOut.Begin(); } }

private void NewListButton_Click(object sender, RoutedEventArgs e) { this.Focus(); this.ViewModel.SaveNewList(); }

private void NewListTextBox_KeyUp(object sender, KeyEventArgs e) { if (e.Key == Key.Enter) { this.NewListButton.Focus(); this.ViewModel.SaveNewList(); } }

private void NewListTextBox_GotFocus(object sender, RoutedEventArgs e) {

Page | 31

Page 32: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

this.ViewModel.OnFocusNewListField(); }

private void NewListTextBox_LostFocus(object sender, RoutedEventArgs e) { this.ViewModel.OnBlurNewListField(); }

protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e) { e.Cancel = true; this.selectedItem = null; this.PageTransitionOut.Begin(); } }

32. Inside the Windows Phone 7 Project, add a new folder named ViewModels, inside it, create a new class named BaseViewModel and replace its implementation with the following code

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 BaseViewModel - C#)

C#

using System.ComponentModel;using System.Windows;namespace MyTodo.Phone.Online.ViewModels{ public abstract class BaseViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged;

protected virtual void NotifyPropertyChanged(string propertyName) { if (this.PropertyChanged != null) { this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } public bool IsDesignTime { get { return DesignerProperties.IsInDesignTool; } } }}

Page | 32

Page 33: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

Note: The BaseViewModel is an abstraction that handles the changes in the properties of the ViewModels, by implementing the INotifyPropertyChanged, these changes impact on the bound elements in the UI.

33. Add a new class ListsViewModel and replace its implementation with the following.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 ListViewmodel - C#)

C#

using System; using System.Linq; using System.Collections.Generic; using System.Collections.ObjectModel; using MyTodo.Phone.Online.Services; using MyTodo.Phone.Online.Infrastructure; using MyTodo.Phone.Online.Models; using MyTodo.Phone.Online.ViewModels;

public class ListsViewModel : BaseViewModel {

private const string NewListPlaceHolderName = "New List Name";

private ITodoService todoService; private ObservableCollection<TaskList> items; private bool isBusy; private string newListName;

public ListsViewModel() : this(ServiceFactory.GetTodoService()) { }

public ListsViewModel(ITodoService todoService) { this.Items = new ObservableCollection<TaskList>(); this.IsBusy = true; this.NewListName = NewListPlaceHolderName; this.todoService = todoService; }

public ObservableCollection<TaskList> Items { get {

Page | 33

Page 34: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

return this.items; }

set { if (this.items != value) { this.items = value; this.NotifyPropertyChanged("Items"); this.NotifyPropertyChanged("HasItems"); } } }

public bool IsBusy { get { return this.isBusy; }

set { if (this.isBusy != value) { this.isBusy = value; this.NotifyPropertyChanged("IsBusy"); this.NotifyPropertyChanged("HasItems"); } } }

public bool HasItems { get { return this.Items != null && this.Items.Count() > 0; } }

public string NewListName { get { return this.newListName; }

set {

Page | 34

Page 35: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

if (this.newListName != value) { this.newListName = value; this.NotifyPropertyChanged("NewListName"); } } }

public void Reload() { this.IsBusy = true; this.todoService.GetLists(delegate(IEnumerable<TaskList> lists) { lock (this.Items) { this.Items.Clear(); foreach (var list in lists.OrderBy(o => o.Name)) this.Items.Add(list); this.IsBusy = false; } }); }

public void SaveNewList() { if (!string.IsNullOrEmpty(this.NewListName) && this.NewListName != NewListPlaceHolderName) { var taskList = new TaskList { IsPublic = 0, Name = this.NewListName }; this.IsBusy = true; this.NewListName = NewListPlaceHolderName;

this.todoService.AddList( taskList, delegate(TaskList savedList) { this.Reload(); }); } }

public void OnFocusNewListField() { if (this.NewListName == NewListPlaceHolderName) { this.NewListName = string.Empty; } }

Page | 35

Page 36: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

public void OnBlurNewListField() { if (string.IsNullOrEmpty(this.NewListName)) { this.NewListName = NewListPlaceHolderName; } } }

Note: As you can see, the ListsViewModel simply contains the Lists, which are populated by the Reload method, and a SaveNewList method that contains the logic for creating a new list. Both methods leverage the OnlineTodoService to consume the WCF Data Service exposed by the MVC Application.

34. In order to authenticate the user, you will add the Login Page and View Model. Since this functionality is out of the scope of this exercise, you will simply grab them from the Assets Folder.

a. First, add both LoginView.xaml and the LoginView.xaml.cs files located in Assets\Views into the Views folder located in the WP7 Project.

b. Next, add the LoginViewModel.cs file located in the Assets\ViewModels into the ViewModels folder located in the WP7 Project.

35. To add the converters used by the Views, add a new folder named Converters.

36. Add all the converters located in Assets\Converters folder inside the Converters folder you have just created.

37. Finally, open the WMAppManifest.xml located in the Properties folder, and set the DefaultTask as follows.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 DefaultTaskLoginView)

XML

... <Tasks> <DefaultTask Name ="_default" NavigationPage="Views/LoginView.xaml"/> </Tasks> <Tokens>...

Page | 36

Page 37: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

38. Verification: Press CTRL +F5 to launch myTodo service hosted in Compute Emulator. Then right click on the MyTodo.Phone.Online project file, click on Debug, and select Start new instance in order to launch the application in the Windows Phone Emulator. Remember to wait until myTodo service is working and the website is opened before running the instance.

Note: Make sure you select Windows Phone 7 Emulator to run the application in emulator. When deploying the Windows Phone 7 application to a Windows Phone 7 device you can select Windows Phone 7 Device.

Page | 37

Page 38: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

Figure 11WP7 client consuming WCF Data Services

39. We have a WP7 application consuming WCF Data Services in a simple way. Now we are going to complete the myTodo’s functionality.

40. Create a new folder called Resources, and create a folder called Images into it.

41. Add the images located into Assets\Resources\Images to the recently created folder Images.

42. Add both TasksViewModel.cs and TaskDetailViewModel.cs located into Assets\ViewModels to ViewModels project folder.

43. Add TasksView.xaml, TasksView.xaml.cs, TaskDetailView.xaml and TaskDetailView.xaml.cs located into Assets\Views to Views project folder.

44. Add the MouseLeftButtonUp handler to the Listbox Items into the ListsView.xaml file.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 MouseLeftButtonUp)

Page | 38

Page 39: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

XAML

... <ListBox Visibility="{Binding HasItems, Converter={StaticResource VisibilityConverter}}" x:Name="ItemsListBox" ItemsSource="{Binding Items}" MouseLeftButtonUp="ItemsListBox_MouseLeftButtonUp"> <ListBox.ItemTemplate>...

45. Implement all the remaining methods into the OnlineTodoService.cs class that throw a NotImplementedException.

Figure 12Methods to be implemented

46. To do that, remove the following methods: GetListAndTasks, DeleteTask, UpdateTask, AddTask. Then copy the following code in this place.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 OnlineTodoServiceMethods- C#)

C#

... public void GetListAndTasks(Guid listId, Action<TaskList> callback) {

Page | 39

Page 40: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

var requestUri = new Uri(string.Format("{0}TaskLists?$filter=Id eq guid'{1}'&$expand=Tasks", serviceUri, listId), UriKind.Absolute); var ctx = this.GetContext();

ctx.BeginExecute<TaskList>( requestUri, delegate(IAsyncResult asyncResult) { try { var result = ctx.EndExecute<TaskList>(asyncResult).FirstOrDefault(); Deployment.Current.Dispatcher.BeginInvoke(() => { callback(result); }); } catch (Exception ex) { Debug.WriteLine(ex.ToString()); Deployment.Current.Dispatcher.BeginInvoke(() => { if (this.ServiceException != null) { this.ServiceException(this, new ServiceExceptionArgs { Exception = ex }); } }); } }, null); }

public void AddTask(TaskList list, Task task, Action<Task> callback) { var dataService = this.GetContext(); task.TimestampUpdate = DateTime.UtcNow; task.UserName = App.UserName; dataService.AttachTo("TaskLists", list); dataService.AddRelatedObject(list, "Tasks", task); dataService.BeginSaveChanges( delegate(IAsyncResult asyncResult) { try { var response = dataService.EndSaveChanges(asyncResult).First(); Deployment.Current.Dispatcher.BeginInvoke(() => { callback(asyncResult.AsyncState as Task); }); }

Page | 40

Page 41: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

catch (Exception ex) { Debug.WriteLine(ex.ToString()); Deployment.Current.Dispatcher.BeginInvoke(() => { if (this.ServiceException != null) { this.ServiceException(this, new ServiceExceptionArgs { Exception = ex }); } }); } }, task ); }

public void DeleteTask(Task task, Action<Task> callback) { var dataService = this.GetContext(); dataService.AttachTo("Tasks", task); dataService.DeleteObject(task); dataService.BeginSaveChanges( delegate(IAsyncResult asyncResult) { try { var response = dataService.EndSaveChanges(asyncResult).First(); var deletedTask = asyncResult.AsyncState as Task; Deployment.Current.Dispatcher.BeginInvoke(() => { callback(deletedTask); }); } catch (Exception ex) { Debug.WriteLine(ex.ToString()); Deployment.Current.Dispatcher.BeginInvoke(() => { if (this.ServiceException != null) { this.ServiceException(this, new ServiceExceptionArgs { Exception = ex }); } }); } }, task ); }

Page | 41

Page 42: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

public void UpdateTask(Task task, Action<Task> callback) { var dataService = this.GetContext(); dataService.AttachTo("Tasks", task); dataService.UpdateObject(task); dataService.BeginSaveChanges( delegate(IAsyncResult asyncResult) { try { var response = dataService.EndSaveChanges(asyncResult).First(); Deployment.Current.Dispatcher.BeginInvoke(() => { callback(asyncResult.AsyncState as Task); }); } catch (Exception ex) { Debug.WriteLine(ex.ToString()); Deployment.Current.Dispatcher.BeginInvoke(() => { if (this.ServiceException != null) { this.ServiceException(this, new ServiceExceptionArgs { Exception = ex }); } }); } }, task ); } }...

47. Finally, you need to update the MyTodoDataService.svc.cs located on the MyTodo.Web project to support these operations. To accomplish this, add the following code below the QueryTaskLists function.

(Code Snippet – Windows Phone 7 and The Cloud - Ex01 MyTodoDataServiceMethods- C#)

C#

...[ChangeInterceptor("TaskLists")]public void OnChangeTaskList(TaskList taskList, UpdateOperations operation){ // authenticate

Page | 42

Page 43: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

if (this.UserIdentity == null) { throw new DataServiceException(404, "Resource Not Found"); }

// authorize if (operation == UpdateOperations.Change || operation == UpdateOperations.Delete) { if (operation == UpdateOperations.Change) taskList.UserName = this.UserIdentity.Name; var originalList = this.CurrentDataSource.TaskLists.FirstOrDefault(o => o.Id == taskList.Id); if (originalList == null || !originalList.UserName.Equals(this.UserIdentity.Name, StringComparison.OrdinalIgnoreCase)) { throw new DataServiceException(404, "Resource Not Found"); } } else if (operation == UpdateOperations.Add) { taskList.UserName = this.UserIdentity.Name; if (taskList.Id == Guid.Empty) { taskList.Id = Guid.NewGuid(); } }}

[ChangeInterceptor("Tasks")]public void OnChangeTask(Task task, UpdateOperations operation){ // authenticate if (this.UserIdentity == null) { throw new DataServiceException(404, "Resource Not Found"); }

// authorize if (operation == UpdateOperations.Add) { var originalList = this.CurrentDataSource.TaskLists.FirstOrDefault(o => o.Id == task.TaskList.Id); if (originalList == null || !originalList.UserName.Equals(this.UserIdentity.Name, StringComparison.OrdinalIgnoreCase)) { throw new DataServiceException(404, "Resource Not Found");

Page | 43

Page 44: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

} } else if (operation == UpdateOperations.Change || operation == UpdateOperations.Delete) { var originalTask = this.CurrentDataSource.Tasks.FirstOrDefault(o => o.Id == task.Id); var originalList = this.CurrentDataSource.TaskLists.FirstOrDefault(o => o.Tasks.FirstOrDefault(t => t.Id == task.Id) != null); if (originalTask == null || !originalList.UserName.Equals(this.UserIdentity.Name, StringComparison.OrdinalIgnoreCase)) { throw new DataServiceException(404, "Resource Not Found"); } }

switch (operation) { case UpdateOperations.Add: if (task.Id == Guid.Empty) { task.Id = Guid.NewGuid(); }

task.StartDate = DateTime.UtcNow; task.DueDate = DateTime.MaxValue; goto case UpdateOperations.Change; case UpdateOperations.Change: task.UserName = this.UserIdentity.Name; task.TimestampUpdate = DateTime.UtcNow; break; }}

protected override void HandleException(HandleExceptionArgs args){ Debug.Fail("DataService.Error", args.Exception.ToString()); base.HandleException(args);}

48. Verification: Press CTRL +F5 to launch myTodo service hosted in Compute Emulator. Then right click on the MyTodo.Phone.Online project file, click on Debug, and select Start new instance in order to launch the application in the Windows Phone Emulator. Remember to wait until myTodo service is working and the website is opened before running the instance. Now you have the whole WP7 application consuming myTodo’s WCF Data Services layer.

Page | 44

Page 45: az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../Lab.docx · Web viewIn this hands-on lab, you will be creating a simplified version of the MyTODO sample; first, you will expose its

Summary

By completing this hands-on lab you have learned how to:

Create a WCF Data Service that expose entities and business logic

Consume a WCF Data Service from Windows Phone 7

Authenticate a user from Windows Phone 7 against a WCF Service

Debug a Windows Phone 7 application with the Phone Emulator

Page | 45