如何在没有 HttpClientFactory 的情况下将多个 HttpMessageHandler 添加到 HttpClient

How to add multiple HttpMessageHandler to HttpClient without HttpClientFactory

我有一个使用 HttpClient 发出网络请求的控制台应用程序。

var client = new HttpClient();

我正在尝试添加多个 HttpMessageHandler to it (custom implementations of DelegatingHandler, really) but the constructor for HttpClient only takes a single HttpMessageHandler

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

没关系...

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

但这不能编译:

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

因为我的目标是 .NET 4.0,所以我不能使用 HttpClientFactory,这个问题的解决方案通常是这样解释的:

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

因为我只是在控制台应用程序中,而不是在 ASP.NET 应用程序中,所以我也不能这样做:

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

我查看了 HttpClientFactory 的 源代码,其中似乎没有任何内容不能在 .NET 4.0 中编译,但我的自己的工厂("inspired" 由微软的源代码),有没有办法手动添加许多 HTTP 消息处理程序到 HttpClient?

要在 .Net 4.0 平台上使用控制台应用程序,最好的解决方案是将 httpConfiguration 传递给您的 webapi 库,或者如果您没有 WebAPI 代码,只需将此代码写入 global.ascx webhost [=17] 文件=]申请

     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());

   }

在您的控制台应用程序中,放置您托管 webapi 的虚拟主机的 uri

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

DelegatingHandler 有一个 protected constructor that takes a handler 作为内部处理程序。如果您可以控制所有自定义处理程序,我认为您可以添加一个调用受保护构造函数的 public 构造函数,例如:

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

然后将它们链接起来:

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

我想你可以这样做:

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

这样您就不需要为了链接目的而创建 CustomHandler。 这就是 DelegatingHandler 的真正目的。

在使用 AddHttpClient extension method 的情况下,您可以使用 IHttpClientBuilder 来配置 DelegateHandler-s 的所有链。

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