Using WebClient and HttpWebRequest

The WebClient and HttpWebRequest classes can both be used for retrieving data from a Web service. WebClient is most useful for one-time retrieval of data from a Web service, or downloading remote resources (for more information on this see, "Downloading Content on Demand") and I think, is somewhat easier to use. HttpWebRequest is perhaps a bit less user-friendly, but will enable you to set headers and generally offers more control over a Web service request.

The following code demonstrates how to make the same request using both classes. I’ve set up a simple Silverlight control that contains two buttons, a text box to capture user input, and a text block to display the content returned from the Web service. The first example demonstrates how to make a request using WebClient, the second demonstrates the same request using HttpWebRequest. Both requests are asynchronous.

First, I show you the simple UI. It’s some stack panels, two buttons, a text box that accepts user and a text block to display the output from the Web service.

<StackPanel Background="White">

    <StackPanel Orientation="Horizontal">

        <Button Width="250" Content="Click for request with

          HttpWebRequest" Click="Button1_Click"  />

        <Button Width="250" Content="Click for request with WebClient"

            Click="Button2_Click" />

    </StackPanel>

    <StackPanel Orientation="Horizontal">

    <TextBlock  Text="Enter a number between 1-5: " />

    <TextBox  Text="1" x:Name="numTextBox" Width="20" />

    </StackPanel>

    <TextBlock x:Name="resultBlock" />

</StackPanel>

The request will go to a Digg Web service that returns the last photos uploaded to its gallery service. This service that allows you to use the URL to specify the expected response type and the number of photos to return, which I will do. In addition, I must specify an AppKey, which is required by the Digg Web service. It’s important to notice that Digg has the required cross domain policy in place to allow calls from my Silverlight application.

First I declare the base URL used by both WebClient and HttpWebRequest:

string baseUri = https://services.digg.com/galleryphotos?count;

 

I’ll use the same URL with both WebClient and HttpWebRequest, but since I'll append the number of photos to return, I’ll build the complete URL for each request using the specified number and the AppKey. In addition, I'll specify an xml response by appending &type=xml to the end of the URL.

To call the service by using WebClient, declare a WebClient object, and in the Page constructor associate its DownloadStringCompleted event with a handler.

WebClient client = new WebClient();

 

client.DownloadStringCompleted +=

   new DownloadStringCompletedEventHandler(

    client_DownloadStringCompleted);

In Button1_Click, I call DownloadStringAsync, passing the complete URL that includes the number specified by the user.

private void Button1_Click(object sender, RoutedEventArgs e)

{

    client.DownloadStringAsync

      (new Uri(baseUri + numTextBox.Text +

      "&appkey=http%3A%2F%2Fsilverlight.net&type=xml"));

}

In the DownloadStringCompleted event-handler, I check that the Error property of the event args is null, and either output the response or the error message to the text block.

void client_DownloadStringCompleted(object sender,

  DownloadStringCompletedEventArgs e)

{

    if (e.Error == null)

  resultBlock.Text = "Using WebClient: "+ e.Result;

  else

  resultBlock.Text = e.Error.Message;

}

 

Next, I’ll made the same call using HttpWebRequest. In Button2_Click, I create the HttpWebRequest by calling HttpWebRequest.Create, passing the URL built from the baseUrl, the user-specified photo count, and AppKey. I call BeginGetResponse on the request, passing the callback method as a new AsyncCallback object and the request object as the state parameter. I’ll use the request object in the callback to retrieve the response.

private void Button2_Click(object sender, RoutedEventArgs e)

{

    HttpWebRequest request =

      (HttpWebRequest)HttpWebRequest.Create(new Uri(baseUri +

  numTextBox.Text + "&appkey=http%3A%2F%2Fsilverlight.net&type=xml"));

  request.BeginGetResponse(new AsyncCallback(ReadCallback),

       request);

}

In the callback method, ReadCallback, I retrieve the request with the AsyncState property of the asynchronousResult parameter, and get the response by calling EndGetResponse on the request. Finally I use a StreamReader to read the results and output them to the TextBlock.

private void ReadCallback(IAsyncResult asynchronousResult)

{

    HttpWebRequest request =

      (HttpWebRequest)asynchronousResult.AsyncState;

    HttpWebResponse response =

      (HttpWebResponse)request.EndGetResponse(asynchronousResult);

   using (StreamReader streamReader1 =

      new StreamReader(response.GetResponseStream()))

      {

      string resultString = streamReader1.ReadToEnd();

      resultBlock.Text = "Using HttpWebRequest: " + resultString;

      }

}

The results are essentially the same either way, but for a more complex request, if I need to specify headers, content type or need more control over my request, I’ll need to use HttpWebRequest.

Hopefully this helps you get started with your own Web service calls. If you need more help, see my previous post, which also points to two other great blog posts on the topic.

--Cheryl