How to use ConfigurePrimaryHttpMessageHandler generic

10,573

Derive from HttpClientHandler or any HttpMessageHandler derived class.

public class MyHttpClientHandler : HttpClientHandler {

    public MyHttpClientHandler() {
        //Set here whatever you need to get configured
    }

    //...override members as needed
}

Call your handler using appropriate extension

services
    .AddHttpClient<IMyService, MyService>()
    .ConfigurePrimaryHttpMessageHandler<MyHttpClientHandler>();

The MyHttpClientHandler will be resolved from a scoped service provider that shares the lifetime of the handler being constructed.

Share:
10,573
Manuel Navarro
Author by

Manuel Navarro

Updated on June 14, 2022

Comments

  • Manuel Navarro
    Manuel Navarro almost 2 years

    I want to add an HttClientHandler for a Typed HttpClient in order to include certificate authentication.

    All the examples I'm finding on the internet are like this:

    services.AddHttpClient<IMyService, MyService>()
        .ConfigurePrimaryHttpMessageHandler(() =>
        {
            return new HttpClientHandler()
            {
                // Set here whatever you need to get configured
            };
        });
    

    But I don't want to include all the logic to obtain the certificate here, so I would like to use the generic version of ConfigurePrimaryHttpMessageHandler<> and write my own message handler to include the certificate in the request.

    The problem is that I'm struggling to understand how should I implement the message handler... should I inherit from HttpClientHandler ??

    Help, please!

    Update

    As I initially suspected, and @Nkosi confirmed, to derive from HttpClient handler is the way to go in this scenario. The code in the ends looks similar to this:

    public class MyHttpClientHandler : HttpClientHandler
    {
        private readonly IMyConfiguration _myConfiguration;
    
        public MyHttpClientHandler(IMyConfiguration myConfiguration)
        {
            _myConfiguration = myConfiguration;
    
            using (var certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine))
            {
                certStore.Open(OpenFlags.ReadOnly);
                var certCollection = certStore.Certificates.Find(
                    X509FindType.FindBySerialNumber,
                    _myConfiguration.MyCertificateSerial,
                    true);
    
                X509Certificate2 certificate = certCollection[0];    
                ClientCertificateOptions = ClientCertificateOption.Manual;
                SslProtocols = System.Security.Authentication.SslProtocols.Tls12;
                ClientCertificates.Add(certificate);
            }
        }
    }
    

    Very important!

    On the other hand while trying to register my http client handler I noticed it was never being called. After some googling I found out that currently there's an open bug about that (https://github.com/aspnet/Extensions/issues/851). So until it get's fixed you need configure your handler this way:

    services.AddTransient<MyHttpClientHandler>();
    
    services.AddHttpClient<IMyService, MyService>()
        .ConfigurePrimaryHttpMessageHandler(sp => sp.GetRequiredService<MyHttpClientHandler>());
    
  • Manuel Navarro
    Manuel Navarro over 4 years
    Please refer to the update I added in the original post, as currently there's a bug at configuring primary Http message handlers using the generic version.