Should HttpClient instances created by HttpClientFactory be disposed?

.Net CoreDotnet HttpclientIdisposableasp.net Core-2.1Httpclientfactory

.Net Core Problem Overview


So, I've registered a named client with the services collection in my Startup.cs:

services.AddHttpClient(someServiceName, 
                       client => client.BaseAddress = baseAddress);

and now can inject an IHttpClientFactory from my service provider.

Using this IHttpClientFactory, I conjure up a client instance:

var client = httpClientFactory.CreateClient(someServiceName)

Once upon a time, it was necessary to be very careful about the disposing of HttpClient instances, as it was rarely the right thing to do.

However, now we have HttpClientFactory, does this matter any more? Should/Can this client be disposed without worry? e.g.

using (var httpClient = httpClientFactory.CreateClient(someServiceName))
using (var response = await httpClient.PostAsync(somePath, someData))
{
    var content = await response.Content.ReadAsAsync<SomeResponse>();
    //...
}

.Net Core Solutions


Solution 1 - .Net Core

No. You should not dispose of your client. To be more general, you should not dispose of anything retrieved via a DI container, which in ASP.NET Core is by default the service collection. The lifetime is managed by the DI container, so if you dispose of the client, but it's later injected into something, you'll get an ObjectDisposedException. Let the container handle disposal.

This is actually a common confusion with IDisposable classes. You should personally only implement IDisposable if your class itself owns dependencies. If all its dependencies are injected, you should not implement IDisposable, since it doesn't own anything that needs disposal. Likewise, you should not dispose of anything injected into your class, as it doesn't own those dependencies. Only dispose of things you specifically new up. If you don't see the keyword new, you probably shouldn't be disposing.

Solution 2 - .Net Core

Calling the Dispose method is not required but you can still call it if you need for some reasons.

Proof: HttpClient and lifetime management

> Disposal of the client isn't required. Disposal cancels outgoing requests and guarantees the given HttpClient instance can't be used after calling Dispose. IHttpClientFactory tracks and disposes resources used by HttpClient instances. The HttpClient instances can generally be treated as .NET objects not requiring disposal.

Check the source of DefaultHttpClientFactory:

public HttpClient CreateClient(string name)
{
    if (name == null)
    {
        throw new ArgumentNullException(nameof(name));
    }

    var handler = CreateHandler(name);
    var client = new HttpClient(handler, disposeHandler: false);

    var options = _optionsMonitor.Get(name);
    for (var i = 0; i < options.HttpClientActions.Count; i++)
    {
        options.HttpClientActions[i](client);
    }

    return client;
}

The instance of HttpMessageHandler stores unmanaged resources of the HttpClient. In the classical scenario the HttpClient creates the instance of HttpMessageHandler and disposes it while itself disposing.

You can see in the above code that different instances of HttpClient shares single instance of HttpMessageHandler and doesn't dispose it (disposeHandler: false).

So, the call of the HttpClient.Dispose does nothing. But it's not dangerous.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionspenderView Question on Stackoverflow
Solution 1 - .Net CoreChris PrattView Answer on Stackoverflow
Solution 2 - .Net CoreMark ShevchenkoView Answer on Stackoverflow