HttpClient is a modern HTTP client for .NET. It provides a flexible and extensible API for accessing all things exposed through HTTP. HttpClient has been available for a while as part of WCF Web API preview 6 but is now shipping as part of ASP.NET Web API and directly in .NET 4.5. You can also download it using NuGet – we just use the following three NuGet packages in this blog:

  1. System.Net.Http: The main NuGet package providing the basic HttpClient and related classes
  2. System.Net.Http.Formatting: Adds support for serialization, deserialization as well as for many additional features building on top of System.Net.Http
  3. System.Json: Adds support for JsonVaue which is a mechanism for reading and manipulating JSON documents

In case you haven’t played with HttpClient before, here is a quick overview of how it works:

HttpClient is the main class for sending and receiving HttpRequestMessages and HttpResponseMessages. If you are used to using WebClient or HttpWebRequest then it is worth noting that HttpClient differs in some interesting ways – here’s how to think about an HttpClient:

  1. An HttpClient instance is the place to configure extensions, set default headers, cancel outstanding requests and more.
  2. You can issue as many requests as you like through a single HttpClient instance.
  3. HttpClients are not tied to particular HTTP server or host; you can submit any HTTP request using the same HttpClient instance.
  4. You can derive from HttpClient to create specialized clients for particular sites or patterns
  5. HttpClient uses the new Task-oriented pattern for handling asynchronous requests making it dramatically easier to manage and coordinate multiple outstanding requests.

Kicking the Tires

We will be diving into lots of details in the near-future around features, extensibility, serialization, and more but let’s first kick the tires by sending a request to the World Bank Data Web API. Please see List of ASP.NET Web API and HttpClient Samples for the complete sample solution. The service provides all kinds of information about countries around the world. It exposes the data both as XML and as JSON but in this sample we download it as JSON and use JsonValue to traverse the request for interesting information without having to create a CLR type on the client side:

   1: /// <summary>
   2: /// Sample download list of countries from the World Bank Data sources at http://data.worldbank.org/
   3: /// </summary>
   4: class Program
   5: {
   6:     static string _address = "http://api.worldbank.org/countries?format=json";
   7:  
   8:     static void Main(string[] args)
   9:     {
  10:         // Create an HttpClient instance
  11:         HttpClient client = new HttpClient();
  12:  
  13:         // Send a request asynchronously continue when complete
  14:         client.GetAsync(_address).ContinueWith(
  15:             (requestTask) =>
  16:             {
  17:                 // Get HTTP response from completed task.
  18:                 HttpResponseMessage response = requestTask.Result;
  19:  
  20:                 // Check that response was successful or throw exception
  21:                 response.EnsureSuccessStatusCode();
  22:  
  23:                 // Read response asynchronously as JsonValue and write out top facts for each country
  24:                 response.Content.ReadAsAsync<JsonArray>().ContinueWith(
  25:                     (readTask) =>
  26:                     {
  27:                         Console.WriteLine("First 50 countries listed by The World Bank...");
  28:                         foreach (var country in readTask.Result[1])
  29:                         {
  30:                             Console.WriteLine("   {0}, Country Code: {1}, Capital: {2}, Latitude: {3}, Longitude: {4}",
  31:                                 country.Value["name"],
  32:                                 country.Value["iso2Code"],
  33:                                 country.Value["capitalCity"],
  34:                                 country.Value["latitude"],
  35:                                 country.Value["longitude"]);
  36:                         }
  37:                     });
  38:             });
  39:  
  40:         Console.WriteLine("Hit ENTER to exit...");
  41:         Console.ReadLine();
  42:     }
  43: }

The HttpResponseMessage contains information about the response including the status code, headers, and any entity body. The entity body is encapsulated in HttpContent which captures content headers such as Content-Type, Content-Encoding, etc. as well as the actual content. The content can be read using any number of ReadAs* methods depending on how you would like to consume the data. In the sample above, we read the content as JsonArray so that we can navigate the data and get the information we want.

Trying out .Net 4.5

An exciting feature in .NET 4.5 is the language support for asynchronous programming that makes programming Tasks even easier. Using the new async and await language keywords, we can replace the “ContinueWith” pattern in the sample above and get something that looks very clean like this:

   1: static string _address = "http://api.worldbank.org/countries?format=json";
   2:  
   3: static async void Run()
   4: {
   5:     // Create an HttpClient instance
   6:     HttpClient client = new HttpClient();
   7:  
   8:     // Send a request asynchronously continue when complete
   9:     HttpResponseMessage response = await client.GetAsync(_address);
  10:  
  11:     // Check that response was successful or throw exception
  12:     response.EnsureSuccessStatusCode();
  13:  
  14:     // Read response asynchronously as JsonValue and write out top facts for each country
  15:     JsonArray content = await response.Content.ReadAsAsync<JsonArray>();
  16:  
  17:     Console.WriteLine("First 50 countries listed by The World Bank...");
  18:     foreach (var country in content[1])
  19:     {
  20:         Console.WriteLine("   {0}, Country Code: {1}, Capital: {2}, Latitude: {3}, Longitude: {4}",
  21:             country.Value["name"],
  22:             country.Value["iso2Code"],
  23:             country.Value["capitalCity"],
  24:             country.Value["latitude"],
  25:             country.Value["longitude"]);
  26:     }
  27: }
  28:  
  29: static void Main(string[] args)
  30: {
  31:     Run();
  32:     Console.WriteLine("Hit ENTER to exit...");
  33:     Console.ReadLine();
  34: }

Have fun!

Henrik

del.icio.us Tags: ,,,,,