HttpResponseMessage.Content.ReadAsStreamAsync() vs HttpResponseMessage.Content.ReadAsStringAsync()
Asked Answered
A

3

16
var request = new HttpRequestMessage(HttpMethod.Get, $"api/Items");
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

using (var response = await _httpClient.SendAsync(request))
{
   response.EnsureSuccessStatusCode();
   var stream = await response.Content.ReadAsStreamAsync();        

     using (var streamReader = new StreamReader(stream))
     {
       using (var jsonTextReader = new JsonTextReader(streamReader))
       {
         var jsonSerializer = new JsonSerializer();
         var data =  jsonSerializer.Deserialize<Item>(jsonTextReader);
       }
     }
}

...

var request = new HttpRequestMessage(HttpMethod.Get, "api/Items");
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await _httpClient.SendAsync(request);

response.EnsureSuccessStatusCode();

var content = await response.Content.ReadAsStringAsync();
var data = JsonConvert.DeserializeObject<List<Item>>(content);

I've run this two examples and I'm curious what is the difference between them that always getting same result, ReadAsStreamAsync is much faster then ReadAsStringAsync.

Antiscorbutic answered 24/6, 2020 at 20:33 Comment(2)
When you do ReadAsString you are essentially deserializing twice.Acrolein
@Acrolein Can you tell me more about this, why ReadAsString deserializing twice?Antiscorbutic
S
10

Under the hood, HttpClient stores content in MemoryStream. So, basically calling ReadAsStreamAsync just returns a reference to the stream. In the case of calling ReadAsStringAsync, ToArray method is called on memory stream so an additional copy of data is created.

Siusan answered 31/8, 2021 at 21:30 Comment(0)
G
4

You can check description for ReadAsStreamAsync and for ReadAsStringAsync

In few words - you can send to request content not only string. And ReadAsStreamAsync is only way for you here. If your response content is string - you can use both. But Stream is faster in Any Time.

This gives good explanation about memory allocation and perfomanse in these cases.

Gardas answered 24/6, 2020 at 20:42 Comment(4)
Yes and I want to know why is stream faster?Above links which you shared, there is not any information by comparing themAntiscorbutic
added one more linkGardas
and again there is no information by comparing this two, only describes readasstreamasync functionality to use more optimallyAntiscorbutic
+1 for the link to the article - that article has a good explanation with examples of the differences and, in particular, how to use the ReadAsStreamAsync method.Bricklayer
I
0

This answer is not directly related to the question but rather to the code I see.

As I can see you do the deserialization in a synchronous manner, instead you should do something like this:

using HttpClient httpClient = new();

using HttpResponseMessage response = await httpClient.GetAsync(
    "...",
    HttpCompletionOption.ResponseHeadersRead
).ConfigureAwait(false);

response.EnsureSuccessStatusCode();

Stream responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
IAsyncEnumerable<WeatherForecast> weatherForecasts = JsonSerializer.DeserializeAsyncEnumerable<WeatherForecast>(
    responseStream,
    new JsonSerializerOptions
    {
        PropertyNameCaseInsensitive = true,
        DefaultBufferSize = 128
    });

await foreach (WeatherForecast weatherForecast in weatherForecasts)
{
    ...
}

Please be aware that: DefaultBufferSize while passing JsonSerializerOptions to the DeserializeAsyncEnumerable method. This is very important if one wants to achieve streaming behavior. Internally, DeserializeAsyncEnumerable will read from the stream until the buffer is full or the stream has ended. If the buffer size is large (and the default is 16KB) there will be a significant delay in asynchronous iteration (in fact you can see irregularity in the above output resulting from exactly that).

Creds - https://www.tpeczek.com/2021/07/aspnet-core-6-and-iasyncenumerable.html

Interment answered 19/2, 2023 at 17:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.