如何在ASP.NET Core 中使用IHttpClientFactory


利用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還負責處理一些常見問題,比如日志記錄。

原文鏈接:https://www.infoworld.com/article/3586176/how-to-use-ihttpclientfactory-in-aspnet-core.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM