Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"stream was not readable" ArgumentException when using ReadAsStreamAsync with StreamReader

I have the following piece of code to read and process the response of a Http get request using StreamReader:

try
{
    Stream stream = await ExecuteRequestAsync(uriBuilder.Uri, HttpMethod.Get).ConfigureAwait(false);
    if (stream != null)
    {
        using (StreamReader sr = new StreamReader(stream))
        {
            using (JsonTextReader reader = new JsonTextReader(sr))
            {
                ...
            }
        }
    }
}
catch (Exception ReadingStreamException)
{

}

private async Task<stream> ExecuteRequestAsync(Uri uri, HttpMethod method)
{
    Stream stream;
    using (HttpRequestMessage httpRequestMessage = new HttpRequestMessage(method, uri))
    {
    try
    {
        stopwatch.Start();
        using (HttpResponseMessage responseMessage = await this.httpClient.SendAsync(httpRequestMessage).ConfigureAwait(false))
        {
            stream = await responseMessage.Content.ReadAsStreamAsync().ConfigureAwait(false);
        }
    }
    catch(Exception GettingStreamException)
    {
        // Error checking code
    }

    return stream;
}

The line using (StreamReader sr = new StreamReader(stream)), is throwing an exception to ReadingStreamException of type ArgumentException with the detail "Stream was not readable". Is there something wrong with the above code?

like image 801
Romonov Avatar asked Jun 23 '15 00:06

Romonov


1 Answers

This happens because when you dispose HttpResponseMessage, it disposes the underlying stream. From the source:

private HttpContent content;
protected virtual void Dispose(bool disposing)
{
    if (disposing && !disposed)
    {
        disposed = true;
        if (content != null)
        {
            content.Dispose();
        }
    }
}

You can either copy the stream, or simply not dispose HttpResponseMessage, as you'll dispose the underlying stream anyway when passing it to StreamReader. I'd go with the latter:

private async Task<Stream> ExecuteRequestAsync(Uri uri, HttpMethod method)
{
    Stream stream = null;
    using (HttpRequestMessage httpRequestMessage = new HttpRequestMessage(method, uri))
    {
       try
       {
          stopwatch.Start();
          HttpResponseMessage responseMessage = await httpClient
                                                      .SendAsync(httpRequestMessage)
                                                      .ConfigureAwait(false);

          stream = await responseMessage.Content.ReadAsStreamAsync()
                                                .ConfigureAwait(false);
       }
       catch(Exception GettingStreamException)
       {
          // Error checking code
       }  
    }
    return stream;
}
like image 92
Yuval Itzchakov Avatar answered Sep 26 '22 12:09

Yuval Itzchakov