I am using the System.Net.Http.HttpClient
to do some client-side HTTP communication. I've got all of the HTTP in one spot, abstracted away from the rest of the code. In one instance I want to read the response content as a stream, but the consumer of the stream is well insulated from where the HTTP communication happens and the stream is opened. In the spot responsible for HTTP communication I am disposing of all of the HttpClient
stuff.
This unit test will fail at Assert.IsTrue(stream.CanRead)
:
[TestMethod]
public async Task DebugStreamedContent()
{
Stream stream = null; // in real life the consumer of the stream is far away
var client = new HttpClient();
client.BaseAddress = new Uri("https://www.google.com/", UriKind.Absolute);
using (var request = new HttpRequestMessage(HttpMethod.Get, "/"))
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
//here I would return the stream to the caller
stream = await response.Content.ReadAsStreamAsync();
}
Assert.IsTrue(stream.CanRead); // FAIL if response is disposed so is the stream
}
I typically try to dispose of anything IDisposable
at the earliest possible convenience but in this case, disposing the HttpResponseMessage
also disposes the Stream
returned from ReadAsStreamAsync
.
So it seems like the calling code needs to know about and take ownership of the response message as well as the stream, or I leave the response message undisposed and let the finalizer deal with it. Neither option feels right.
This answer talks about not disposing the HttpClient
. How about the HttpRequestMessage
and/or HttpResponseMessage
?
Am I missing something? I am hoping to keep the consuming code ignorant of HTTP but leaving all these undisposed objects around goes against year of habit!
IDisposable
needs to be disposed – Incommensurableasync
per se. The rules are the same either way: don't dispose the object until you're done with it. The same thing would apply using the synchronous version. So, use the returnedStream
inside theusing
. If you need to use theStream
outside the context where the request is created, you'll have to set up a different mechanism to dispose of it at the right time. – Skimmerclient
anyway, so if you're comfortable with that, don't bother with the other stuff either. As for the answer you reference, note that it pertains to the scenario where you reuse theHttpClient
object; frankly, it should be obvious that if you want to reuse it, you don't dispose it. The guidance doesn't say anything at all about whether it's legitimate to just let the object disposal happen via finalization (and IMHO it's very poor form to). – Skimmer