Saturday, May 4, 2013

Consuming a JSON REST API Asynchronously

A few days ago I published this article about how to consume a JSON REST API in .NET in a very simple and straight forward way. The approach uses the default JSON serializer that comes with .NET and the .NET WebClient() class.

In this article I want to extend the first example on how to consume the API response asynchronously. I’ll continue to build on top of the previous example. If you didn’t read the first article, you can find it here. You can also download the sample project here.

Let’s create the asynchronous method we will call. Open the WeatherApiClient class and add a new static method called GetWeatherForecastAync().

image

Add the string URL variable with the JSON API endpoint we will use to retrieve the weather information. In this example we are using the OpenWeatherMap API. Then, create the WebClient instance and called asyncClient.

To use the asynchronous mechanism, we want to be able to call the API, and move on to do something else. Then, when the API response is returned, we want to be notified and keep on parsing the response and serializing the corresponding object. Achieving this is straight forward with WebClient.

First, attach an event handler for the WebClient’s DownloadStringCompleted event (if you press tab twice in Visual Studio, it will create it for you). Then, call the DownloadStringAsync() method passing a new Uri with the API endpoint’s URL.

image

Then, inside the DownloadStringCompleted() event handler, just copy and paste the same serialization logic we used before in the synchronous method.

image

Add the call to the new asynchronous method in the main program to make sure we can test it. Keep in mind that since we are using a simple console application, if you run the project, the main thread will finish before you get the response and your event handler is called. Just add a Console.ReadLine() at the end so the program keeps running until to press any key.

image

Place a breakpoint in the method and the event handler so you can see what is going on and make sure you are getting the forecast data.

image

image

There you go. An easy and simple way to consume a JSON API asynchronously and deserialize the JSON response into your C# object. You can get the updated sample project from my Github repo here.

It is important to point out that this is just one way of doing it, and my goal was to do it as easily and clean as possible. However, there are other JSON serializers available like JSONFX and JSON.NET (which is supposed to be the fastest JSON serializer out there, although I haven’t tested it myself). Check Hanselman’s article on the subject.

Having a class contract for the native serializer might not be the best solution. JSON.NET offers you dynamic object serialization. However, not matching some of JSON object’s properties, or not having the JSON object returning some of the properties, won’t break the serialization.

It depends on your needs and what you are trying to do. Also, the make sure to understand the API responses and implications of consuming it. Think about versioning, support, etc.

Here you can find a nice API checklist article to keep in mind.

Here’s the main source code (in case you don’t want to download the sample project):

  1: public static void GetWeatherForecastAsync()
  2: {
  3:     // format the Url according to parameters and service endpoint
  4:     var url = "http://api.openweathermap.org/data/2.1/find/city?lat=51.50853&lon=-0.12574&cnt=10";
  5: 
  6:     // Async Consumption
  7:     var asyncClient = new WebClient();
  8:     asyncClient.DownloadStringCompleted += asyncClient_DownloadStringCompleted;
  9:     asyncClient.DownloadStringAsync(new Uri(url));
 10: 
 11:     // Do something else...
 12: }
 13: 
 14: static void asyncClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
 15: {
 16:     // Create the Json serializer and parse the response
 17:     DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(WeatherData));
 18:     using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(e.Result)))
 19:     {
 20:         var weatherData = (WeatherData)serializer.ReadObject(ms);
 21:     }
 22: }

1 comment:

  1. Really enjoyed reading your last two articles on "Consuming a JSON REST API". Clear,, concise and educational. Thanks - Nazik

    ReplyDelete