简体   繁体   中英

How to add multiple HttpMessageHandler to HttpClient without HttpClientFactory

I have a console application that uses HttpClient to make web requests.

var client = new HttpClient();

I'm trying to add multiple HttpMessageHandler to it (custom implementations of DelegatingHandler , really) but the constructor for HttpClient only takes a single HttpMessageHandler .

class LoggingHandler : DelegatingHandler { //... }
class ResponseContentProcessingHandler : DelegatingHandler { //... }

this is ok...

var client = new HttpClient(new LoggingHandler()); // OK

but this doesn't compile:

var client = new HttpClient(
                new LoggingHandler(), 
                new ResponseContentProcessingHandler()); // Sadness

Because I'm targeting .NET 4.0, I cannot use HttpClientFactory , which is how the solution to this problem is commonly explained:

HttpClient client = HttpClientFactory.Create(
                       new LoggingHandler(),
                       new ResponseContentProcessingHandler());

Because I'm just in a console application, rather than in an ASP.NET application, I can't do this either:

GlobalConfiguration.Configuration
                   .MessageHandlers
                   .Add(new LoggingHandler()
                   .Add(new ResponseContentProcessingHandler());

I've looked at the source for HttpClientFactory and there doesn't seem to be anything in there that wouldn't compile in .NET 4.0, but short of rolling my own factory ("inspired" by Microsoft's source code), is there a way to manually add many HTTP message handlers to the HttpClient ?

DelegatingHandler has a protected constructor that takes a handler for the inner handler. If you have control over all your custom handlers, I would think you can add a public constructor that calls the protected constructor, like:

public class CustomHandler : DelegatingHandler
{
    public CustomHandler(HttpMessageHandler innerHandler) : base(innerHandler)
    {
    }
}

and chain them thus:

var client = new HttpClient(new CustomHandler(new OtherCustomerHandler(new HttpClientHandler())));

I think you can just do something like this:

var loggingHandler = new LoggingHandler();
var responseContentProcessingHandler =  new ResponseContentProcessingHandler();
loggingHandler.InnerHandler = responseContentProcessingHandler;
var client = new HttpClient(loggingHandler);

So that you don't need to create a CustomHandler just for the chaining purpose. That's really the purpose of DelegatingHandler.

In case of using AddHttpClient extension method you can use IHttpClientBuilder to configure all chain of DelegateHandler -s.

ServiceCollection
    .AddHttpClient("MyClient")
    .ConfigureHttpMessageHandlerBuilder(builder =>
    {
        builder.AdditionalHandlers.Add(builder.Services.GetRequiredService<YourFirstHandler>());
        builder.PrimaryHandler = builder.Services.GetRequiredService<YourLastHandler>();
    });
} 

To Achieve with Console application on .Net 4.0 platform,best possible solution is to pass httpConfiguration to your webapi library or if you dont hold WebAPI code just write this code in global.ascx file of webhost asp.net application

     protected void Application_Start(object sender, EventArgs e)
             {
        var config = GlobalConfiguration.Configuration;
        WebAPIConfig.Configure(config);


    }

   //Code that will configure all message handlers in webapi    
          public static void Configure(HttpConfiguration configure)
   {


        configure.MessageHandlers.Add(new xyzhandler());
       configure.MessageHandlers.Add(new ABCHandler());

   }

In your Console Application,place uri of your webhost hosting webapi

   private const string APiUri="http://localhost/api/get"
   using(HttpClient cleint=new HttpClient()){
     var response await cleint.GetAsync(ApiUri);
    ....
               }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM