1 / 45

Charles Petzold www.charlespetzold.com

Networking. Charles Petzold www.charlespetzold.com. Agenda. WebClient HttpWebRequest Consuming REST services Consuming ASMX and WCF services Push notification services Tile scheduling. Silverlight vs. SWP. WebClient. Event-based HTTP networking API Asynchronous operation only

papina
Télécharger la présentation

Charles Petzold www.charlespetzold.com

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Networking Charles Petzold www.charlespetzold.com

  2. Agenda • WebClient • HttpWebRequest • Consuming REST services • Consuming ASMX and WCF services • Push notification services • Tile scheduling

  3. Silverlight vs. SWP

  4. WebClient • Event-based HTTP networking API • Asynchronous operation only • Commonly used to download assets • DownloadStringAsync - String • OpenReadAsync – Stream (binary) • Also features uploading methods • Fires progress and completion events and supports cancellation of pending requests • Event handlers execute on calling thread

  5. Downloading an Image File WebClientwc = new WebClient(); wc.OpenReadCompleted += new OpenReadCompletedEventHandler(OnOpenReadCompleted); wc.OpenReadAsync(new Uri ("http://www.wintellect.com/images/Bandit.jpg")); ... private void OnOpenReadCompleted(object sender, OpenReadCompletedEventArgs e) { if (e.Error == null) { BitmapImage bi = new BitmapImage(); bi.SetSource(e.Result); MyImage.Source = bi; } }

  6. Downloading a Zipped Image File WebClientwc = new WebClient(); wc.OpenReadCompleted += new OpenReadCompletedEventHandler(OnOpenReadCompleted); wc.OpenReadAsync(new Uri("http://www.wintellect.com/images/Images.zip")); ... private void OnOpenReadCompleted(object sender, OpenReadCompletedEventArgs e) { if (e.Error == null) { StreamResourceInfo sri1 = new StreamResourceInfo(e.Result, null); StreamResourceInfo sri2 = Application.GetResourceStream(sri1, new Uri("Bandit.jpg", UriKind.Relative)); BitmapImage bi = new BitmapImage(); bi.SetSource(sri2.Stream); MyImage.Source = bi; } }

  7. Updating a Progress Bar WebClientwc = new WebClient(); wc.DownloadProgressChanged+= OnDownloadProgressChanged; ... private void OnDownloadProgressChanged(object sender, DownloadProgressChangedEventArgse) { Progress.Value = e.ProgressPercentage; }

  8. Downloading an RSS Feed WebClientwc = new WebClient(); wc.OpenReadCompleted += new OpenReadCompletedEventHandler(OnOpenReadCompleted); wc.OpenReadAsync(new Uri("...")); ... private void OnOpenReadCompleted(object sender, OpenReadCompletedEventArgse) { if (e.Error == null) { using (StreamReader reader = new StreamReader(e.Result)) { string rss = reader.ReadToEnd(); // TODO: Parse the feed } } }

  9. WebClient

  10. HttpWebRequest • Delegate-based HTTP networking API • Asynchronous operation only • Generally used to call untyped HTTP services • e.g., REST services • Completion methods called on background threads from CLR thread pool • Use Dispatcher.BeginInvoke to update UI

  11. Calling a REST Service (GET) HttpWebRequest request = (HttpWebRequest) HttpWebRequest.Create (new Uri("http://contoso.com/weather/98052")); request.BeginGetResponse (new AsyncCallback(OnGetResponseCompleted), request); ... private void OnGetResponseCompleted(IAsyncResultar) { HttpWebRequest request = (HttpWebRequest)ar.AsyncState; HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(ar); using (StreamReader reader = new StreamReader(response.GetResponseStream())) { string result = reader.ReadToEnd(); ... } }

  12. Calling a REST Service (POST) HttpWebRequest request = (HttpWebRequest) HttpWebRequest.Create (new Uri("http://contoso.com/weather")); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; request.BeginGetRequestStream(new AsyncCallback (OnGetRequestStreamCompleted), request); ... private void OnGetRequestStreamCompleted(IAsyncResultar) { HttpWebRequest request = (HttpWebRequest)ar.AsyncState; using (StreamWriter writer = new StreamWriter(request.EndGetRequestStream(ar))) { writer.Write("98052"); // Write input into body of request } request.BeginGetResponse(new AsyncCallback(OnGetResponseCompleted), request); } ... private void OnGetResponseCompleted(IAsyncResultar) { ... }

  13. HttpWebRequest

  14. ASMX and WCF Services • Callable through WCF Web service proxies • Use Visual Studio's "Add Service Reference" command to generate proxies • Selected WCF bindings supported • BasicHttpBinding (WS-I Basic Profile 1.0) • Custom HTTP binding with binary message encoding • No PollingDuplexHttpBinding or NetTcpBinding • Asynchronous operation only

  15. Creating a WCF Service • Use "Add New Item" -> "Silverlight-Enabled WCF Service" command in Visual Studio

  16. Calling a WCF Service ZipCodeServiceClient proxy = new ZipCodeServiceClient(); proxy.GetCityAndStateFromZipCodeCompleted+= new EventHandler<GetCityAndStateFromZipCodeCompletedEventArgs> (GetCityAndStateFromZipCodeCompleted); proxy.GetCityAndStateFromZipCodeAsync("98052"); ... private void GetCityAndStateFromZipCodeCompleted(object sender, GetCityAndStateFromZipCodeCompletedEventArgs e) { if (e.Error == null) { Place place= e.Result; // Method returns Place object string city = place.City; string state = place.State; ... } }

  17. WCF Services

  18. Push Notifications • Asynchronous notifications delivered to phones • Utilize Microsoft Push Notification Service (PNS) • Hosted in Azure; massively scalable and reliable • Battery- and bandwidth-efficient alternative to polling • Three types of notifications • Raw notifications • Toast notifications • Tile notifications • Toast and tile notifications work if app isn't running

  19. How Push Notifications Work Count Phone app requests URI from PNS Phone transmits URI to Web service 3 1 2 PNS returns URI 5 Service calls PNS using transmitted URI 4 PNS sends notification to phone Microsoft Push Notification Service Your Web Service

  20. Raw Notifications • Delivered only when app is active • If app is inactive, call to PNS returns HTTP 200 OK with notification status == "Suppressed" • Payload can be text or binary data • 1K maximum payload size

  21. Raw Notification Wire Format POST uri HTTP/1.1 X-NotificationClass: interval Host: uri Content-Type: application/*; charset=UTF-8 Content-Length: length payload

  22. Sending a Raw Notification HttpWebRequestrequest = HttpWebRequest.Create(uri) as HttpWebRequest; request.Method= WebRequestMethods.Http.Post; request.Headers.Add("X-NotificationClass", "3"); // Send immediately using (Stream stream = request.GetRequestStream()) { byte[] payload = Encoding.UTF8.GetBytes(message); stream.Write(payload, 0, payload.Length); } HttpWebResponse response = request.GetResponse() as HttpWebResponse;

  23. Toast Notifications • Delivered even when application is inactive • Displayed in toast window at top of screen • Clicking toast window activates application • Also delivered when application is active • Not automatically displayed • App decides what to do

  24. Toast Notification Wire Format POST uri HTTP/1.1 X-NotificationClass: interval X-WindowsPhone-Target: toast Host: uri Content-Type: application/*; charset=UTF-8 Content-Length: length <?xml version="1.0" encoding="utf-8"?> <wp:Notificationxmlns:wp="WPNotification"> <wp:Toast> <wp:Text1>MessageCaption</wp:Text1> <wp:Text2>MessageText</wp:Text2> </wp:Toast> </wp:Notification>

  25. Sending a Toast Notification HttpWebRequestrequest = HttpWebRequest.Create(uri) as HttpWebRequest; request.Method= WebRequestMethods.Http.Post; request.ContentType= "text/xml"; request.Headers["X-WindowsPhone-Target"] = "toast"; request.Headers.Add("X-NotificationClass", "2"); // Send immediately using (Stream stream = request.GetRequestStream()) { byte[] payload = Encoding.UTF8.GetBytes (String.Format(_template, caption, message)); request.ContentLength= payload.Length; stream.Write(payload, 0, payload.Length); } HttpWebResponse response = request.GetResponse() as HttpWebResponse;

  26. Tile Notifications • Update tiles pinned on start screen ("live tiles") • Change tile background image • Local or remote images • Max size 80K; must load in under 15 seconds • Change count displayed in tile's upper-right corner • Change title displayed along tile's bottom border Count Title

  27. Tile Notification Wire Format POST uri HTTP/1.1 X-NotificationClass: interval X-WindowsPhone-Target: tile Host: uri Content-Type: application/*; charset=UTF-8 Content-Length: length <?xml version="1.0" encoding="utf-8"?> <wp:Notificationxmlns:wp="WPNotification"> <wp:Tile> <wp:BackgroundImage>BackgroundImageUri</wp:BackgroundImage> <wp:Count>Count</wp:Count> <wp:Title>Title</wp:Title> </wp:Tile> </wp:Notification>

  28. Sending a Tile Notification HttpWebRequestrequest = HttpWebRequest.Create(uri) as HttpWebRequest; request.Method= WebRequestMethods.Http.Post; request.ContentType= "text/xml"; request.Headers["X-WindowsPhone-Target"] = "token"; request.Headers.Add("X-NotificationClass", "1"); // Send immediately using (Stream stream = request.GetRequestStream()) { byte[] payload = Encoding.UTF8.GetBytes (String.Format(_template, imageuri, count, title)) request.ContentLength= payload.Length; stream.Write(payload, 0, payload.Length); } HttpWebResponse response = request.GetResponse() as HttpWebResponse;

  29. PNS Response Codes • Calls to PNS return important information in HTTP status codes and custom response headers • X-NotificationStatus • X-SubscriptionStatus • X-DeviceConnectionStatus • Certain response codes must not be ignored • Subscription may be expired • Subscription may require server-side throttling • Response codes documented at http://msdn.microsoft.com/en-us/library/ff941100(v=vs.92).aspx

  30. Sample Response Codes

  31. Handling Response Codes HttpWebResponse response = request.GetResponse() as HttpWebResponse; intstatus = (int)response.StatusCode; string xsubscription = null; if (response.Headers["X-SubscriptionStatus"] != null) xsubscription = response.Headers["X-SubscriptionStatus"].ToString(); if ((xsubscription != null && xsubscription == "Expired") || status == 404 || status == 406 || status == 412) { // Delete the subscription RemoveSubscription(uri); }

  32. HttpNotificationChannel • Class used to connect phone apps to PNS

  33. Opening a Channel channel = HttpNotificationChannel.Find("MyChannel"); if (channel == null) // Create a new channel { channel = new HttpNotificationChannel("MyChannel"); RegisterChannelEventHandlers(channel); channel.Open(); // Generates ChannelUriUpdated event } else // Configure an existing channel { RegisterChannelEventHandlers(channel); BindChannel(channel); // TODO: Send the URI to the Web service }

  34. Binding to Notifications // Configure the channel to report toast notifications if (!channel.IsShellToastBound) channel.BindToShellToast(); // Configure the channel to support tile notifications if (!channel.IsShellTileBound) channel.BindToShellTile();

  35. Handling Raw Notifications channel.HttpNotificationReceived+= OnRawNotificationReceived; . . . void OnHttpNotificationReceived(object sender, HttpNotificationEventArgse) { // Transfer to UI thread if updating the UI Dispatcher.BeginInvoke(() => { // Payload in e.Notification.Body }); }

  36. Handling Toast Notifications channel.ShellToastNotificationReceived += OnToastReceived; ... void OnToastReceived(object sender, NotificationEventArgs e) { // Transfer to UI thread if updating the UI Dispatcher.BeginInvoke(() => { string caption = String.Empty; if (e.Collection.ContainsKey("wp:Text1")) caption = e.Collection["wp:Text1"]; string message = String.Empty; if (e.Collection.ContainsKey("wp:Text2")) message = e.Collection["wp:Text2"]; ... }); }

  37. Handling Tile Notifications This space intentionally left blank

  38. Constraints and Limitations • Limit of one open channel per app • Limit of 15 open channels per device • No way to know ahead of time how many are open • HttpNotificationChannel.Open throws InvalidOperationException when limit is exceeded • Limit of 500 notifications per day per channel • Limit waived for authenticated Web services • Apps that use push notifications must comply with WP7 Application Certification Requirements

  39. Push Notifications

  40. Tile Scheduling • ShellTileSchedule class permits tiles to be updated periodically by downloading them from a server • Does not count against push notification limit • Frequency cannot exceed one update per hour • Options are hourly, daily, weekly, monthly • Max image size 80K; must load in < 15 seconds • Updates suspended when screen is locked or off • Updates fire immediately when screen unlocks

  41. Scheduling Hourly Updates ShellTileSchedulests = new ShellTileSchedule(); sts.Interval = UpdateInterval.EveryHour; sts.MaxUpdateCount = 0; // Run indefinitely sts.Recurrence = UpdateRecurrence.Interval; sts.RemoteImageUri= new Uri(@"http://www.wintellect.com/tiles/hourlyimage.png"); sts.Start();

  42. Performing a One-Time Update x ShellTileSchedulests = new ShellTileSchedule(); sts.Recurrence= UpdateRecurrence.OneTime; sts.StartTime = DateTime.Now; sts.RemoteImageUri = new Uri(@"http://www.wintellect.com/tiles/tile.png"); sts.Start();

  43. Detecting Connectivity Status if (NetworkInterface.GetIsNetworkAvailable()) { // App is connected } else { // App is not connected }

  44. Detecting Status Changes NetworkChange.NetworkAddressChanged += OnNetworkAddressChanged; . . . void OnNetworkAddressChanged(object sender, EventArgs e) { if (NetworkInterface.GetIsNetworkAvailable()) { // App is connected } else { // App is not connected } }

  45. Questions? Charles Petzold www.charlespetzold.com

More Related