Search code examples
asp.netazure-functionsdotnet-httpclient.net-6.0

Getting Cannot access a disposed object. Object name: 'SocketsHttpHandler' exception in .Net 6 Application


In one of my Azure Function app(.Net 6 isolated process) and I am making some http requests with a client certificate. I'm registering my services in the Program.cs like this,

var handler = new HttpClientHandler();
handler.ClientCertificates.Add(clientCertificate);

services.AddHttpClient().Configure<HttpClientFactoryOptions>(
               "myClient", options =>
                   options.HttpMessageHandlerBuilderActions.Add(builder =>
                       builder.PrimaryHandler = handler));

services.AddTransient<IMyCustomClient, MyCustomClient>(provider =>
           new MyCustomClient(provider.GetService<IHttpClientFactory>(),
               cutomParameter1, cutomParameter2));

services.AddSingleton<IMyCustomService, MyCustomService>();

And injecting MyCustomClient in MyCustomService constructor

private readonly IMyCustomClient _myCustomClient;

public PlatformEventManagementService(IMyCustomClient myCustomClient)
{
    _myCustomClient = myCustomClient;
}

var result = await _myCustomClient.GetResponse();

It works fine for some time and getting the below exception after sending many requests.

Cannot access a disposed object. Object name: 'SocketsHttpHandler'.


Solution

  • You are supplying the factory with a single instance of HttpClientHandler to use in all clients. Once the default HandlerLifetime has elapsed (2 minutes) it will be marked for disposal, with the actual disposal occurring after all existing HttpClients referencing it are disposed.

    All clients created after the handler is marked continue to be supplied the soon-to-be disposed handler, leaving them in an invalid state once the disposal is actioned.

    To fix this, the factory should be configured to create a new handler for each client. You may wish to use the simpler syntax shown in the MS documentation.

    // Existing syntax
    services.AddHttpClient().Configure<HttpClientFactoryOptions>(
                    "myClient", options =>
                        options.HttpMessageHandlerBuilderActions.Add(builder =>
                        {
                            var handler = new HttpClientHandler();
                            handler.ClientCertificates.Add(clientCertificate);
                            builder.PrimaryHandler = handler;
                        }));
    
    // MS extension method syntax
    services
        .AddHttpClient("myClient")
        // Lambda could be static if clientCertificate can be retrieved from static scope
        .ConfigurePrimaryHttpMessageHandler(_ =>
        {
            var handler = new HttpClientHandler();
            handler.ClientCertificates.Add(clientCertificate);
            return handler;
        });