利用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我的项目。
- 启动Visual Studio IDE。
- 点击“创立新我的项目”。
- 在“创立新我的项目”窗口中,从模板列表中抉择ASP.NET Core Web应用程序。
- 单击Next。
- 在“配置新我的项目”窗口中,指定新我的项目的名称和地位。
- 能够抉择“将解决方案和我的项目放在同一个目录中”复选框。
- 点击Create。
- 在“创立一个新的ASP.NET Core Web应用程序“窗口中,抉择。NET Core作为运行时,而后抉择asp.net Core作为运行时。NET Core 3.1(或更高版本)。
- 抉择“Web Application (Model-View-Controller)”作为我的项目模板来创立一个新的ASP.NET Core MVC应用程序。
- 确保复选框“启用Docker反对”和“配置HTTPS”没有选中,因为咱们不会在这里应用这些个性。
- 确保身份验证设置为“无身份验证”,因为咱们也不会应用身份验证。
- 单击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还负责解决一些常见问题,比方日志记录。