利用IHttpClientFactory能够无缝创立HttpClient实例,防止手动治理它们的生命周期。

当应用ASP.Net Core开发应用程序时,可能常常须要通过HttpClient调用WebAPI的办法以查看终结点是否失常工作。要实现这一点,通常须要实例化HttpClient并应用该实例来调用你的办法。然而间接应用HttpClient也有一些毛病,次要与手动治理实例的生命周期无关。

你能够应用IHttpClientFactory创立HttpClient来防止这些问题。IHttpClientFactory是在.Net Core 2.1引入的,它提供了一个命名,配置和创立HttpClient实例的外围性能,并能主动治理实例的池化和生命周期。

上面咱们通过代码进一步探讨HttpClient和IHttpClientFactory,以及所设计的概念。要应用提供的代码,你须要装置Visual Studio 2019。

在Visual Studio 2019中创立一个ASP.NET Core MVC我的项目   

假如你的零碎中装置了Visual Studio 2019,请依照上面列出来的步骤创立一个新的ASP.NET Core我的项目。

  1. 启动Visual Studio IDE。
  2. 点击“创立新我的项目”。
  3. 在“创立新我的项目”窗口中,从模板列表中抉择ASP.NET Core Web应用程序。
  4. 单击Next。
  5. 在“配置新我的项目”窗口中,指定新我的项目的名称和地位。
  6. 能够抉择“将解决方案和我的项目放在同一个目录中”复选框。
  7. 点击Create。
  8. 在“创立一个新的ASP.NET Core Web应用程序“窗口中,抉择。NET Core作为运行时,而后抉择asp.net Core作为运行时。NET Core 3.1(或更高版本)。
  9. 抉择“Web Application (Model-View-Controller)”作为我的项目模板来创立一个新的ASP.NET Core MVC应用程序。
  10. 确保复选框“启用Docker反对”和“配置HTTPS”没有选中,因为咱们不会在这里应用这些个性。
  11. 确保身份验证设置为“无身份验证”,因为咱们也不会应用身份验证。
  12. 单击Create。

依照这些步骤将创立一个新的ASP.NET Core MVC应用程序。在新我的项目中,创立一个新的API Controller,并应用默认名称保留它,即ValuesController。咱们将在接下来的局部中应用这个我的项目。

挑战HttpClient

只管HttpClient没有间接实现IDisposable接口,但它扩大了System.Net.Http。HttpMessageInvoker,这个类实现了IDisposable。然而,当应用HttpClient实例时,你不应该手动操作开释它们。只管能够在HttpClient实例上调用Dispose办法,但不举荐这样做。

应该怎么做呢?一种抉择是使HttpClient动态化,或者将HttpClient的非动态实例包装在自定义类中,并使其成为单例类。然而更好的代替办法是应用IHttpClientFactory来生成HttpClient的实例,而后应用该实例来调用操作方法。

IHttpClientFactory 和HttpClientFactory

IHttpClientFactory是一个由DefaultHttpClientFactory类实现的接口,这是一个工厂模式。DefaultHttpClientFactory实现了IHttpClientFactory和IHttpMessageHandlerFactory接口。IHttpClientFactory提供了ASP.NET Core对创立、缓存和解决HttpClient实例提供了杰出的内置反对。

请留神,HttpClientFactory只是一个帮忙类,用于创立应用提供的处理程序配置的HttpClient实例。这个类有以下办法:

Create(DelegatingHandler[])Create(HttpMessageHandler,DelegatingHandler[])CreatePipeline(HttpMessageHandler,IEnumerable<DelegatingHandler>)

重载的HttpClientFactory类的Create办法看起来像这样:

public static HttpClient Create(params DelegatingHandler[] handlers){  return Create(new HttpClientHandler(), handlers);}public static HttpClient Create(HttpMessageHandler innerHandler, params DelegatingHandler[] handlers){  HttpMessageHandler pipeline = CreatePipeline(innerHandler, handlers);  return new HttpClient(pipeline);}

引入HttpClientFactory和IHttpClientFactory是为了更好地治理HttpMessageHandler实例的生命周期。

为什么应用IHttpClientFactory?

当你开释HttpClient实例时,连贯将放弃关上状态长达4分钟。此外,能够在任何工夫点关上socket的数量是有限度的——不能同时关上太多socket。因而,当应用太多HttpClient实例时,可能会耗尽socket。

这就是IHttpClientFactory的意义所在。你能够通过利用IHttpClientFactory来创立用于调用HTTP API办法的HttpClient实例,以防止HttpClient所面临的问题。在ASP.NET Core中实现IHttpClientFactory的次要指标是为了确保应用工厂模式创立HttpClient实例的同时防止socket耗尽。

在ASP.NET Core中注册IHttpClientFactory实例

你能够在Startup类的ConfigureServices办法中,通过调用IServiceCollection实例上的AddHttpClient扩大办法注册一个IHttpClientFactory类型的实例,如下:

public void ConfigureServices(IServiceCollection services){   services.AddControllersWithViews();   services.AddHttpClient();}
将IHttpClientFactory实例注入到控制器

能够通过如下代码将将IHttpClientFactory实例注入到控制器:

public class HomeController : Controller{      private IHttpClientFactory _httpClientFactory;      private readonly ILogger<HomeController> _logger;      public HomeController(ILogger<HomeController> logger,      IHttpClientFactory httpClientFactory)      {            _logger = logger;            _httpClientFactory = httpClientFactory;      }}
在Action中调用HttpClient

要通过应用IHttpClientFactory创立HttpClient,应该调用CreateClient办法。一旦HttpClient实例可用,就能够在HomeController类的index办法中应用以下代码来调用ValuesController类的Get办法。

public async Task<IActionResult> Index(){   HttpClient httpClient = _httpClientFactory.CreateClient();   httpClient.BaseAddress = new Uri("http://localhost:1810/");   var response = await httpClient.GetAsync("/api/values");   string str = await response.Content.ReadAsStringAsync();   List<string> data = JsonSerializer.Deserialize<List<string>>(str);   return View(data);}
应用IHttpClientFactory在ASP.NET Core中创立和治理HttpClient实例

有几种办法能够在应用程序中应用IHttpClientFactory。这包含间接应用IHttpClientFactory、应用命名client和类型client。

根本的或个别的应用模式,即间接应用IHttpClientFactory—在后面的大节中曾经探讨过了。请参考“注册一个IHttpClientFactory实例”一节,该节探讨了如何注册HttpClient实例。

如果你想应用不同配置的HttpClient实例,以下是一个不错的抉择。上面的代码片段阐明了如何创立。

services.AddHttpClient("github", c =>{    c.BaseAddress = new Uri("https://api.github.com/");    c.DefaultRequestHeaders.Add("Accept",    "application/vnd.github.v3+json");    c.DefaultRequestHeaders.Add("User-Agent", "This is a test user agent");});

第二种办法是应用包装了HttpClient实例的自定义类,该自定义类封装了通过HTTP协定调用所有终结点的逻辑。上面的代码片段阐明了如何定义自定义HttpClient类。

public class ProductService : IProductService{    private IHttpClientFactory _httpClientFactory;    private readonly HttpClient _httpClient;    private readonly string _baseUrl = "http://localhost:1810/";    public ProductService(HttpClient httpClient)    {        _httpClient = httpClient;    }    public async Task<Catalog> GetAllProducts()    {        _httpClient = _httpClientFactory.CreateClient();        _httpClient.BaseAddress = new Uri(_baseUrl);        var uri = "/api/products";        var result = await _httpClient.GetStringAsync(uri);        return JsonConvert.DeserializeObject<Product>(result);    }}

通过以下代码注册自定义的client:

services.AddHttpClient<IProductService, ProductService>();
将MessageHandler增加到命名管道中

MessageHandler是扩大自HttpMessageHandler类,它能够承受HTTP申请并返回HTTP响应。如果你想构建本人的MessageHandler,你应该创立一个继承DelegatingHandler的类。

你能够将HttpMessageHandler增加到申请解决管道中。能够在Startup类的ConfigureServices办法中应用以下代码将HttpMessageHandler增加到管道中。

public void ConfigureServices(IServiceCollection services){    services.AddHttpClient("github", c =>    {        c.BaseAddress = new Uri("https://api.github.com/");    })    .AddHttpMessageHandler<DemoHandler>();    services.AddTransient<DemoHandler>();}

IHttpClientFactory是一个自.net Core 2.1以来就可用的工厂类。如果你应用IHttpClientFactory来创立HttpClient实例,那么底层HttpClientMessagehandler实例的池化和生命周期将主动治理。IHttpClientFactory还负责解决一些常见问题,比方日志记录。