ASP.NET Web API supports asynchronous actions using the new Task-based programming model introduced in .NET 4. In .NET 4.5 the model has improved further and in addition is supported directly from C# using the new async and await keywords (see “Visual Studio Asynchronous Programming” for background).
What this means is that you can have actions that look like this:
as well as
and even this
The benefit of writing Task-based actions is that you don’t block a thread on the server even if things take a long time to complete and that allows the server to scale better and be more responsive.
In the blog “Push and Pull Streams using HttpClient” we described how to use push and pull streams with HttpContent. As HttpRequestMessage, HttpResponseMesssage, and HttpContent apply to both client side (as part of HttpClient) as well as server side (as part of ASP.NET Web API) the push vs. pull model described in that blog applies equally well to the server side.
In this blog we expand on the topic of reading request content using asynchronous streaming within an action.
Reading Request Body Asynchronously
In the first scenario we implement a POST action that takes a JSON entity body and writes it to another stream. Note that the action returns Task<HttpResponseMessage> which means that the action completes when the task completes. The important part of this action is line 11 where we copy the content from the request to another stream (we describe the SummaryStream below):
This is essentially all you have to do – the rest is just filler but if you want to dive in a little more then keep going! The first thing the action does is checking that the content is actually JSON. To do this we use a little extension method that we have added for this purpose:
To see what is going on when reading the content we create a special stream called SummaryStream that simply indicates when it gets called by writing to the console. You don’t have to use this but if you want to try it out then it looks like this:
The DelegatingStream which SummaryStream derives from is nothing more than delegating every call to the inner stream. It looks like this:
Trying It Out
To run the sample we start it in self host as usual.
Note: By default the max message size in self host is 64k so to accept larger request sizes we set it to 1M and also turn on streaming so that we don’t buffer the whole thing in memory at any point in time.
We then use Fiddler to submit an HTTP POST request with an JSON request body. That is, we open the Composer tab and fill in a POST request with whatever JSON content you want to submit:
The resulting output to the console shows that the data is written asynchronously to the SummaryStream: