Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does HttpClient.PostAsync buffer response?

Tags:

c#

httpclient

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?

like image 504
koruyucu Avatar asked May 27 '15 06:05

koruyucu


People also ask

What is httpclient get async post async send async?

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.

How to create a new record using httppost with httpclient postasync?

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:

What can I do to improve the performance of my httpclient?

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.

What is httpclient in 4+?

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.


1 Answers

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:

  • Use SendAsync
  • Don't use HttpClient (HttpWebRequest is a bit more complicated, but gives you way more control)
like image 145
Luaan Avatar answered Sep 21 '22 19:09

Luaan