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
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.
In this specific case, there are no finalizers. Neither HttpResponseMessage or HttpRequestMessage implement a finalizer (and that's a good thing!). If you don't dispose of either of them, they will get garbage collected once the GC kicks in, and the handle to their underlying streams will be collected once that happens.
As long as you're using these objects, don't dispose. Once done, dispose of them. Instead of wrapping them in a using statement, you can always explicitly call Dispose once you're done. Either way the consuming code doesn't need to have any knowledge underlying http requests.
Dealing with Disposes in .NET is both easy, and hard. For sure.
Streams pull this same nonsense... Does disposing the Buffer also then automatically dispose of the Stream it wrapped? Should it? As a consumer, should I even know whether it does?
When I deal with this stuff, I go by some rules:
So, you've got an HttpClient, an HttpRequestMessage, and an HttpResponseMessage. The lifetimes of each of them, and any Disposable they make, must be respected. Therefore, your Stream should never be expected to survive outside of the Dispoable lifetime of HttpResponseMessage, becuase you didn't instantiate the Stream.
In your above scenario, my pattern would be to pretend that getting that Stream was really just in a Static.DoGet(uri) method, and the Stream you return would HAVE to be one of our own making. That means a second Stream, with the HttpResponseMessage's stream .CopyTo'd my new Stream (routing through a FileStream or a MemoryStream or whatever best fits your situation)... or something similar. Because:
So use disposables like catch-and-release... make them, snag the results for yourself, release them as quickly as possible. And don't confuse optimization for correctness, especially from classes that you did not yourself author.
You can also take stream as input parameter, so the caller has complete control over type of the stream as well as its disposal. And now you can also dispose httpResponse before control leaves the method.
Below is the extension method for HttpClient
public static async Task HttpDownloadStreamAsync(this HttpClient httpClient, string url, Stream output)
{
using (var httpResponse = await httpClient.GetAsync(url).ConfigureAwait(false))
{
// Ensures OK status
response.EnsureSuccessStatusCode();
// Get response stream
var result = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
await result.CopyToAsync(output).ConfigureAwait(false);
output.Seek(0L, SeekOrigin.Begin);
}
}