如何在ASP.NET Core 中使用IHttpClientFactory

碼農譯站發表於2021-02-18

利用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

相關文章