Recently I encountered performance issues when using HttpClients.PostAsync on .Net 4.5.1. Originally server (Owin + WebApi) was buffering response before sending. This was causing huge memory usage overhead (serialized response size is > 1Gb). After I turned on response streaming on the server client literally stopped working. It turned out that reason was buffer re-allocation on the client when reading response from server. I checked HttpClient implementation and found this interesting part in HttpClient.SendAsync
method:
if (result.Content == null || completionOption == HttpCompletionOption.ResponseHeadersRead)
{
this.SetTaskCompleted(request, linkedCts, tcs, result);
}
else
{
this.StartContentBuffering(request, linkedCts, tcs, result);
}
So when completionOption
is not ResponseHeadersRead
response is always buffered. According to SendAsync documentation implementation of SendAsync is consistent with the intent.
Now, as PostAsync
is implemented sending ResponseContentRead
, response stream is always buffered on POSTs. So question is why does PostAsync have to wait (and buffer) for whole response to arrive before processing continues?
HttpClient GetAsync, PostAsync, SendAsync in C# July 18, 2018 7 Comments HttpClient is a library in the Microsoft.NET framework 4+ that is used for GET and POST requests. Let’s go through a simple example of using HttpClient to GET and POST JSON from a web application.
Now, to create a new record using our REST service, we will use HttpPost with HttpClient PostAsync. We will create a function PostURI which calls HttpClient PostAsync, then returns the StatusCode:
Don't use .Result. Stream the response instead of storing the whole response in a string. If you really care about performance, create a custom json deserializer. Reuse HttpClient (or use IHttpClientFactory). All code in this blog post can be found here together with instructions on how to run the benchmarks.
HttpClient is a library in the Microsoft .NET framework 4+ that is used for GET and POST requests. Let’s go through a simple example of using HttpClient to GET and POST JSON from a web application.
There's the obvious part - if you don't specify HttpCompletionOption.ResponseHeadersRead
, the Task
will only complete when the whole response is read; you have to store the response data somewhere in the meantime.
Why doesn't PostAsync
allow you to specify HttpCompletionOption.ResponseHeadersRead
? Probably because it's not really all that useful, most of the time. POST
is for posting data, not for retrieving it - that's GET
's job. HttpClient
was designed around WebAPIs and "REST" services, with proper use of HTTP verbs.
If you need to use POST
to retrieve such large amounts of data, you have two basic options:
SendAsync
HttpClient
(HttpWebRequest
is a bit more complicated, but gives you way more control)If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With