利用IHttpClientFactory能够无缝建立HttpClient实例,避免手动管理它们的生命周期。html
当使用ASP.Net Core开发应用程序时,可能常常须要经过HttpClient调用WebAPI的方法以检查终结点是否正常工做。要实现这一点,一般须要实例化HttpClient并使用该实例来调用你的方法。可是直接使用HttpClient也有一些缺点,主要与手动管理实例的生命周期有关。git
你可使用IHttpClientFactory建立HttpClient来避免这些问题。IHttpClientFactory是在.Net Core 2.1引入的,它提供了一个命名,配置和建立HttpClient实例的核心功能,并能自动管理实例的池化和生命周期。github
下面咱们经过代码进一步讨论HttpClient和IHttpClientFactory,以及所设计的概念。要使用提供的代码,你须要安装Visual Studio 2019。json
在Visual Studio 2019中建立一个ASP.NET Core MVC项目 api
假设你的系统中安装了Visual Studio 2019,请按照下面列出来的步骤建立一个新的ASP.NET Core项目。缓存
1. 启动Visual Studio IDE。app
2. 点击“建立新项目”。asp.net
3. 在“建立新项目”窗口中,从模板列表中选择ASP.NET Core Web应用程序。socket
4. 单击Next。async
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还负责处理一些常见问题,好比日志记录。
原文连接:https://www.infoworld.com/article/3586176/how-to-use-ihttpclientfactory-in-aspnet-core.html