×
Namespaces

Variants
Actions
(Difference between revisions)

Making a HTTP request and listening its completion in Windows Phone

From Nokia Developer Wiki
Jump to: navigation, search
hamishwillee (Talk | contribs)
m (Hamishwillee - Addition to article of: Category:Windows Phone 7.5)
r2d2rigo (Talk | contribs)
m (R2d2rigo - Broken source code link.)
(3 intermediate revisions by 2 users not shown)
Line 1: Line 1:
[[Category:Windows Phone]][[Category:Networking]][[Category:HTTP]]
+
[[Category:Windows Phone]][[Category:Networking]][[Category:HTTP]][[Category:Windows Phone 7.5]][[Category:Windows Phone 8]][[Category:Code Examples]]
{{Abstract|This article include how to make HTTP request using {{Icode|WebClient}} and listening requst completion using EventHandler.}}  
+
{{Abstract|This article demonstrates how to make HTTP requests using both [http://msdn.microsoft.com/en-us/library/system.net.webclient(v=vs.95).aspx WebClient] and [http://msdn.microsoft.com/en-us/library/8y7x3zz2(v=vs.95) HttpWebRequest] and waiting for their completion.}}  
  
 
{{ArticleMetaData <!-- v1.2 -->
 
{{ArticleMetaData <!-- v1.2 -->
|sourcecode= <!-- Link to example source code e.g. [[Media:The Code Example ZIP.zip]] -->
+
|sourcecode= [[Media:HTTPRequests.zip]]
 
|installfile= <!-- Link to installation file (e.g. [[Media:The Installation File.sis]]) -->
 
|installfile= <!-- Link to installation file (e.g. [[Media:The Installation File.sis]]) -->
 
|devices= <!-- Devices tested against - e.g. ''devices=Nokia 6131 NFC, Nokia C7-00'') -->
 
|devices= <!-- Devices tested against - e.g. ''devices=Nokia 6131 NFC, Nokia C7-00'') -->
 
|sdk= WP 7.1 SDK
 
|sdk= WP 7.1 SDK
|platform= Windows Phone 7.5
+
|platform= Windows Phone 7.5, 8
 
|devicecompatability= <!-- Compatible devices e.g.: All* (must have internal GPS) -->
 
|devicecompatability= <!-- Compatible devices e.g.: All* (must have internal GPS) -->
 
|dependencies= <!-- Any other/external dependencies e.g.: Google Maps Api v1.0 -->
 
|dependencies= <!-- Any other/external dependencies e.g.: Google Maps Api v1.0 -->
Line 19: Line 19:
 
|review-by= <!-- After re-review: [[User:username]] -->
 
|review-by= <!-- After re-review: [[User:username]] -->
 
|review-timestamp= <!-- After re-review: YYYYMMDD -->
 
|review-timestamp= <!-- After re-review: YYYYMMDD -->
|update-by= <!-- After significant update: [[User:username]]-->
+
|update-by= [[User:r2d2rigo]]
|update-timestamp= <!-- After significant update: YYYYMMDD -->
+
|update-timestamp= 20121217
 
|creationdate= 20120404
 
|creationdate= 20120404
 
|author= [[User:Mandardac]]
 
|author= [[User:Mandardac]]
Line 26: Line 26:
  
 
== Introduction ==
 
== Introduction ==
HTTPManeger.cs
+
 
 +
One of the most important aspects of smartphones is connectivity and data management. Due to the constraints of processing power and available storage, lots of applications for mobile devices depend on connecting to a remote web service and download the necessary data, be it the result of a search query or a simple image. In this article, we are going to demonstrate how to use both {{Icode|WebClient}} and {{Icode|HttpWebRequest}} to contact a remote server and download string and binary data.
 +
 
 +
== Using WebClient ==
 +
 
 +
First of all, {{Icode|WebClient}} is more limited in Windows Phone than in other .NET versions. We can only use the {{Icode|DownloadStringAsync}} call to download a text-based resource, like the source code of a web page or a XML or JSON based result of a server operation. The good news is that this call is asynchronous and we can subscribe to two events to get the current progress of the operation and the full downloaded data, {{Icode|DownloadProgressChanged}} and {{Icode|DownloadStringCompleted}}, respectively:
  
 
<code csharp>
 
<code csharp>
    public class HTTPManager
+
webClient = new WebClient();
    {
+
webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
        private WebClient webdownloader;
+
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(webClient_DownloadProgressChanged);
        private Uri uri;
+
webClient.DownloadStringAsync(new Uri(downloadUrl));
        public event EventHandler WebRequestCompleted;
+
        public HTTPManager(string url)
+
        {
+
            webdownloader = new WebClient();
+
            uri = new Uri(url);
+
        }
+
        public void MakeRequest()
+
        {
+
            webdownloader.DownloadStringCompleted += new DownloadStringCompletedEventHandler(DataDownloaded);
+
            webdownloader.DownloadStringAsync(uri);
+
        }
+
        public void DataDownloaded(object sender, DownloadStringCompletedEventArgs args)
+
        {
+
            EventHandler handler = WebRequestCompleted;
+
            if (handler != null)
+
            {
+
                handler(sender, args);
+
            }
+
        }
+
 
+
    }
+
 
</code>
 
</code>
  
//now write another class which actully uses above class to make http request and wants to listen request completion
+
The callback for {{Icode|DownloadProgressChanged}} receives a parameter of type {{Icode|DownloadProgressChangedEventArgs}}, which has the following properties:
 +
* '''long BytesReceived''': number of bytes currently downloaded.
 +
* '''int ProgressPercentage''': a value between 0 and 100 indicating the progress percentage of the download.
 +
* '''long TotalBytesToReceive''': total size in bytes of the string to download.
 +
* '''object UserState''': a custom user object to store additional info.
 +
 
 +
{{Warning|'''TotalBytesToReceive''' and '''ProgressPercentage''' properties will only work correctly if the server specifies the '''Content-Length''' header in the response.}}
 +
 
 +
And the callback for {{Icode|DownloadStringCompleted}} has a parameter of type {{Icode|DownloadStringCompletedEventArgs}} with the following properties:
 +
* '''bool Cancelled''': specifies if the operation was cancelled by calling {{Icode|WebClient.CancelAsync}}.
 +
* '''Exception Error''': an exception which includes any errors that could have happened.
 +
* '''string Result''': contains the string downloaded from the remote server.
 +
* '''object UserState''': again, a custom user object to store additional info.
 +
 
 +
=== Common problems when using WebClient ===
 +
 
 +
* Sometimes you will get a '''NotFoundException''' thrown. This can happen by a wide list of causes, from a non-standard header in the response to trying to connect via secure HTTP and providing bad credentials.
 +
* If you have an HTTP sniffing tool like [http://fiddler2.com/ Fiddler2] running and you test your application in the emulator, the above explained '''NotFoundException''' problem can happen too.
 +
* You don't have to {{Icode|Dispose}} or control its deletion in any way; {{Icode|WebClient}} cleans itself after performing the requested actions.
 +
 
 +
== Using HttpWebRequest ==
 +
 
 +
This is a more complex, but at the same time, more customized way of downloading both string and binary data. For example, you can call {{Icode|BeginGetRequestStream}} to obtain a writeable stream if you want to perform a '''POST''' operation, so you have a place where you can write the data you are sending in the HTTP request. If you want a standard '''GET''' request, you call {{Icode|BeginGetResponse}} and pass as its parameter a new {{Icode|AsyncCallback}} containing the callback function that will handle the logic of the operation:
  
 
<code csharp>
 
<code csharp>
    public partial class MainPage : PhoneApplicationPage
+
webRequest = (HttpWebRequest)HttpWebRequest.CreateHttp(imageUrl);
    {
+
webRequest.BeginGetResponse(new AsyncCallback(ResponseCallback), webRequest);
        private string loginurl;
+
 
        // Constructor
+
...
        public MainPage()
+
 
        {
+
private void ResponseCallback(IAsyncResult asyncResult)
            InitializeComponent();
+
{
            MakeRequest();
+
    HttpWebRequest webRequest = (HttpWebRequest)asyncResult.AsyncState;
        }
+
    HttpWebResponse webResponse = (HttpWebResponse)webRequest.EndGetResponse(asyncResult);
        private void MakeRequest() //you can call this method from any event eg.button click,  for simplicity i called it from ctor.
+
 
        {
+
    MemoryStream tempStream = new MemoryStream();
              string loginurl = "http://www.developer.nokia.com/Community/Wiki/Most_Viewed_Windows_Phone_Articles";
+
    webResponse.GetResponseStream().CopyTo(tempStream);
              try
+
}
                {
+
</code>
                    if (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
+
 
                    {
+
=== Common problems when using HttpWebRequest ===
                        MessageBox.Show("N/W connection not available");
+
 
                    }
+
* Windows Phone has an internal mechanism that caches web request, and this affects both {{Icode|WebClient}} and {{Icode|HttpWebRequest}}. This can lead to receiving the same result when querying the same URL twice, even if the response should be different. To solve this, add a random parameter to the end of the URL that you know won't affect the response of the web server in any way.
                    else
+
* If you are using it in '''POST''' mode, remember to call {{Icode|Close}} of the stream that returns {{Icode|EndGetRequestStream}} inside the callback for {{Icode|BeginGetRequestStream}}; otherwise, a race condition exception will be thrown.
                    {
+
* If the server supports it, you can receive a compressed response stream to save extra bandwidth. Just make sure you call {{Icode|webRequest.Headers[HttpRequestHeader.AcceptEncoding] = "gzip"}} before performing the request and, and the response stream will be automatically GZip-compressed (but remember to decompress it before using the data!).
                        HTTPManager httpmanager = new HTTPManager(loginurl);
+
 
                        httpmanager.WebRequestCompleted += this.DownlLodCompleted;
+
== Source code ==
                        httpmanager.MakeRequest();
+
 
                    }
+
You can download an example project showing how to use both {{Icode|WebClient}} and {{Icode|HttpWebRequest}} here: [[Media:HTTPRequests.zip]].
                }
+
                catch (Exception ex)
+
                {
+
                    MessageBox.Show(ex.Message);
+
                }
+
      }
+
      public void DownlLodCompleted(object sender, EventArgs args)
+
      {
+
            MessageBox.Show("Your request is completed.....");
+
      }
+
  }
+
</code>[[Category:Windows Phone 7.5]]
+

Revision as of 21:19, 17 December 2012

This article demonstrates how to make HTTP requests using both WebClient and HttpWebRequest and waiting for their completion.

WP Metro Icon Wifi.png
WP Metro Icon WP8.png
SignpostIcon WP7 70px.png
Article Metadata
Code ExampleTested with
SDK: WP 7.1 SDK
Compatibility
Platform(s): Windows Phone 7.5, 8
Windows Phone 8
Windows Phone 7.5
Article
Created: mandardac (04 Apr 2012)
Updated: r2d2rigo (17 Dec 2012)
Last edited: r2d2rigo (17 Dec 2012)

Contents

Introduction

One of the most important aspects of smartphones is connectivity and data management. Due to the constraints of processing power and available storage, lots of applications for mobile devices depend on connecting to a remote web service and download the necessary data, be it the result of a search query or a simple image. In this article, we are going to demonstrate how to use both WebClient and HttpWebRequest to contact a remote server and download string and binary data.

Using WebClient

First of all, WebClient is more limited in Windows Phone than in other .NET versions. We can only use the DownloadStringAsync call to download a text-based resource, like the source code of a web page or a XML or JSON based result of a server operation. The good news is that this call is asynchronous and we can subscribe to two events to get the current progress of the operation and the full downloaded data, DownloadProgressChanged and DownloadStringCompleted, respectively:

webClient = new WebClient();
webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(webClient_DownloadProgressChanged);
webClient.DownloadStringAsync(new Uri(downloadUrl));

The callback for DownloadProgressChanged receives a parameter of type DownloadProgressChangedEventArgs, which has the following properties:

  • long BytesReceived: number of bytes currently downloaded.
  • int ProgressPercentage: a value between 0 and 100 indicating the progress percentage of the download.
  • long TotalBytesToReceive: total size in bytes of the string to download.
  • object UserState: a custom user object to store additional info.

Warning.pngWarning: TotalBytesToReceive and ProgressPercentage properties will only work correctly if the server specifies the Content-Length header in the response.

And the callback for DownloadStringCompleted has a parameter of type DownloadStringCompletedEventArgs with the following properties:

  • bool Cancelled: specifies if the operation was cancelled by calling WebClient.CancelAsync.
  • Exception Error: an exception which includes any errors that could have happened.
  • string Result: contains the string downloaded from the remote server.
  • object UserState: again, a custom user object to store additional info.

Common problems when using WebClient

  • Sometimes you will get a NotFoundException thrown. This can happen by a wide list of causes, from a non-standard header in the response to trying to connect via secure HTTP and providing bad credentials.
  • If you have an HTTP sniffing tool like Fiddler2 running and you test your application in the emulator, the above explained NotFoundException problem can happen too.
  • You don't have to Dispose or control its deletion in any way; WebClient cleans itself after performing the requested actions.

Using HttpWebRequest

This is a more complex, but at the same time, more customized way of downloading both string and binary data. For example, you can call BeginGetRequestStream to obtain a writeable stream if you want to perform a POST operation, so you have a place where you can write the data you are sending in the HTTP request. If you want a standard GET request, you call BeginGetResponse and pass as its parameter a new AsyncCallback containing the callback function that will handle the logic of the operation:

webRequest = (HttpWebRequest)HttpWebRequest.CreateHttp(imageUrl);
webRequest.BeginGetResponse(new AsyncCallback(ResponseCallback), webRequest);
 
...
 
private void ResponseCallback(IAsyncResult asyncResult)
{
HttpWebRequest webRequest = (HttpWebRequest)asyncResult.AsyncState;
HttpWebResponse webResponse = (HttpWebResponse)webRequest.EndGetResponse(asyncResult);
 
MemoryStream tempStream = new MemoryStream();
webResponse.GetResponseStream().CopyTo(tempStream);
}

Common problems when using HttpWebRequest

  • Windows Phone has an internal mechanism that caches web request, and this affects both WebClient and HttpWebRequest. This can lead to receiving the same result when querying the same URL twice, even if the response should be different. To solve this, add a random parameter to the end of the URL that you know won't affect the response of the web server in any way.
  • If you are using it in POST mode, remember to call Close of the stream that returns EndGetRequestStream inside the callback for BeginGetRequestStream; otherwise, a race condition exception will be thrown.
  • If the server supports it, you can receive a compressed response stream to save extra bandwidth. Just make sure you call {{{1}}} before performing the request and, and the response stream will be automatically GZip-compressed (but remember to decompress it before using the data!).

Source code

You can download an example project showing how to use both WebClient and HttpWebRequest here: Media:HTTPRequests.zip.

625 page views in the last 30 days.
×