Monday, April 14, 2008

Silverlight HTTP Pipeline

In Silverlight 2, by default, only able to talk back to the site of origin server is allowed.
To acheive that the HTTP request is going back to site of origin look at the deployment URI of the XAP and the request URI.
Comparing these two URIs, 3 things must match:
  1. Same domain. http://foo.com  is different than http://bar.foo.com or http://www.foo.com
  2. Same protocol. http://foo.com is different than https://foo.com
  3. Same port. http://foo.com is different than http://foo.com:8080

HTTP requests themselves are:

  • Asynchronous only
  • Can only be initiated on the UI thread
There are two APIs in Silverlight for HTTP communication.  The first is WebClient and the second is HttpWebRequest.

WebClient

WebClient is a great API with a simple, events-based paradigm.  Used to easily download a string or a Stream.

WebClient, behind the scenes, does a GET request and then gives back the result in the form required.  It also automatically resolves relative URIs against the deployment URI of the XAP.


   1: private void DownloadString()
   2: {
   3:     WebClient webClient = new WebClient();
   4:  
   5:     // Hook up events
   6:     webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(webClient_DownloadProgressChanged);
   7:     webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
   8:  
   9:     // Initiate download
  10:     webClient.DownloadStringAsync(new Uri("myfeed.xml", UriKind.Relative));
  11: }
  12:  
  13: void webClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
  14: {
  15:     // Update progress UI
  16:     progressTextBox.Text = e.ProgressPercentage;
  17: }
  18:  
  19: void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
  20: {
  21:     if (e.Error == null)
  22:     {
  23:         // Clear progress UI and show downloaded string
  24:         progressTextBox.Text = "";
  25:         feedTextBox.Text = e.Result;
  26:     }
  27: }
  28:  


HttpWebRequest & HttpWebResponse

HttpWebRequest and HttpWebResponse are the standard .NET HTTP apis.  They are much more powerful than WebClient but also more complex to use. Used to set headers or to issue a POST request.


   1: private void SendPostRequest()
   2: {
   3:     HttpWebRequest request = WebRequest.Create(new Uri("http://foo.com/upload")) as HttpWebRequest;
   4:     request.Method = "POST";
   5:  
   6:     //  Set ContentType through property 
   7:     request.ContentType = "application/xml";
   8:  
   9:     //  Set other headers through Headers property
  10:     request.Headers["x-custom-header"] = "value";
  11:  
  12:     //  Initiate getting request stream
  13:     IAsyncResult asyncResult =
  14:     request.BeginGetRequestStream(new AsyncCallback(RequestStreamCallback), request);
  15: }
  16:  
  17: private void RequestStreamCallback(IAsyncResult ar)
  18: {
  19:     HttpWebRequest request = ar.AsyncState as HttpWebRequest;
  20:  
  21:     // populate request stream
  22:     request.ContentType = "text/xml";
  23:     Stream requestStream = request.EndGetRequestStream(ar);
  24:     StreamWriter streamWriter = new StreamWriter(requestStream, Encoding.UTF8);
  25:     streamWriter.Write("<?xml version="1.0"?>"
  26:                        + "<entry xmlns="http://www.w3.org/2005/Atom">"
  27:                        + "<author>"
  28:                        + "<name>Elizabeth Bennet</name>"
  29:                        + "<email>liz@gmail.com</email>"
  30:                        + "</author>"
  31:                        + "<title type="text">Entry 1</title>"
  32:                        + "<content type="text">This is my entry</content>"
  33:                        + "</entry>");
  34:     streamWriter.Close();
  35:  
  36:     // Make async call for response
  37:     request.BeginGetResponse(new AsyncCallback(ResponseCallback), request);
  38: }
  39:  
  40: private void ResponseCallback(IAsyncResult ar)
  41: {
  42:     HttpWebRequest request = ar.AsyncState as HttpWebRequest;
  43:     WebResponse response = request.EndGetResponse(ar);
  44:  
  45:     // use response.  
  46: }

Thanks to Scorbs for such a in depth explanation, for more please visit http://scorbs.com/.



Blogged with the Flock Browser

1 comment:

David said...

this is great example. I noticed webclient has a progresschanged event, but the other does not. Is it possible to get the progress of the upload process event somehow since the HttpWebRequest is suppose to be more powerful than WebClient. An example would be very much appreciated.