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'.
CodePudding user response:
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 HttpClient
s 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;
});