This blog shows an example of how to build an ASP.NET Web API ApiController that asynchronously talks to multiple other Web APIs in parallel without blocking a thread on the server. Btw, if you have detected a certain theme in these blogs around using Tasks with ASP.NET Web API then you are indeed on to something
Asynchronous programming is an important part of building scalable, robust, and responsive Web applications regardless of whether on client side or server side. Asynchronous programming has traditionally been very complicated leaving it to only the most dedicated to implement it but with the new Task model even complex patterns such as dealing with multiple asynchronous requests in parallel are manageable without braking too much of a sweat. The sample is written using Visual Studio 11 Beta but can be modified to run on Visual Studio 2010 as well.
In the scenario we have an ApiController that exposes a query operation with a single token (in the sequence diagram below the sample query token is “microsoft”). The ApiController then turns around and issues a query to digg and delicious respectively for stories on the query token. When both results are complete, the results are accumulated into a single response that is then sent back to the client. The goal is to do the entire ApiController request asynchronously and to issue the queries to digg and delicious in parallel so that we don’t every block a thread and optimize network utilization.
The response we send back to the client is a collection of “stories” that simply look like this:
Creating the ApiController
Writing the controller involves three things: two helpers for processing the requests for digg and delicious respectively and then the controller to put it all together.
Executing digg Query
First we write a helper for processing the digg query. Here we submit a request, wait for the response, and then process it as JsonValue to build a set of Story instances as defined in the scenario above. As there is no instance state involved the query processing can be done as a static method.
Executing delicious Query
Then we write a similar helper for processing the delicious query. It follows the exact same pattern and also uses JsonValue to read the response and create a set of Story instances. Again, as there is no instance state involved the query processing can be done as a static method.
Writing the Controller
Now we can write the actual ApiController. First we look for a valid query token (we don’t want it to contain any ‘&’ characters). Then we kick off the two helpers in parallel and wait for them to complete (but without blocking a thread using the Task.WhenAll construct). Finally we aggregate the two results and return them to the client.
We of course use HttpClient to submit requests to dig and delicious but as HttpClient can handler requests submitted from multiple threads simultaneously we only need one instance for all requests. This means that the same HttpClient instance is reused for all requests across all ApiController instances.
That’s all we need for the controller – next is just to host it and then run it.
Hosting the Controller
As usual we use a simple command line program for hosting the ApiController and it follows the usual pattern seen in the other blogs:
Trying it Out
To try it out it is useful to use Fiddler as it allows you to see both the incoming and outgoing requests. In the screen capture below we use fiddler to directly compose a request to our localhost ApiController. To the left we can see the two requests to digg and delicious respectively and in the right lower corner you can see the result with parts coming from digg and parts coming from delicious.