JYU Blog

IHttpClientFactory基本用法筆記
2022-01-02 14:05:00

此筆記為紀錄工作上碰到開發需要,使用IHttpClientFactory來建立管控HttpClient生命週期。

依據官方文件(相關參考2)敘述,如果單純使用HttpClient進行Http請求,一般作法建立HttpClient新實體,再透過此建立實體來進行Http請求動作。

正常使用完畢後,我們都會認為會自動釋放,因為該類別內部有繼承IDisposable特性,但是,系統背後通訊端Socket資源佔用問題,卻不會隨著當下實體用完銷毀就跟著被釋放,而後還有其他關於DNS異動調整問題,可以參考相關連結了解詳細。

根據上述狀況,使用官方推薦以IHttpClientFactory方式來進行HttpClient管控,在此筆記紀錄基本用法與單一實體在生命週期內重複利用。


主要專案

  1. .Net Core 3.1 Console 範例主程式
    • 以此Console進行呼叫Web API。
  2. Asp.Net 6 範例Web API
    • Sample API供應範例Console呼叫。

範例Console主程式

安裝相關NutGet套件

建立DI與註冊IHttpClientFactory

ServiceCollection serviceCollection = new ServiceCollection();

serviceCollection.AddHttpClient();

var serviceBuilder = serviceCollection.BuildServiceProvider();

var httpClientFactory = serviceBuilder.GetService<IHttpClientFactory>();

實作Http請求範例內容

依據註入HttpClientFactory方法CreateClient搭配using進行範例實作

IHttpClientFactory httpClientFactory = GetHttpClientFactory();
var baseAddress = new Uri("http://localhost:5030/");
var requestUrl = "WeatherForecast";

using (var client = httpClientFactory.CreateClient("SampleHttpClient"))
{
   // 設定Time Out
   client.Timeout = TimeSpan.FromSeconds(5);
   client.BaseAddress = baseAddress;

   try
   {
      var response = await client.GetAsync(requestUrl);
      var contentStr = await response.Content.ReadAsStringAsync();

      Console.WriteLine(contentStr);
   }
   catch (TaskCanceledException ex)
   {
      Console.WriteLine("TaskCanceledException");
      Console.WriteLine(ex.Message);
      Console.WriteLine("Call Second Api");

      var postContent = new StringContent("");

      var response2 = await client.PostAsync($"{requestUrl}?name=jyu", postContent);

      var contentStr2 = await response2.Content.ReadAsStringAsync();

      Console.WriteLine(contentStr2);
   }
   catch (Exception ex)
   {
      Console.WriteLine("Exception");
      Console.WriteLine(ex.Message);
   }
}

CreateClient可以使用命名模式,參數可帶入自訂命名,如果有在Service註冊時,設定指定命名HttpClient配置實體,可以在實際使用時,依據指定命名取得對應已配置好設定實體,如果未有對應則會建立新實體。

詳細可參考 具名用戶端

上述Http請求行為如下


範例Web API

使用預設建置WeatherForecast Controller模板,原始預設產生GetWeatherForecast API調整如下。

[HttpGet(Name = "GetWeatherForecast")]
public async Task<IEnumerable<WeatherForecast>> Get()
{
   // 加入此行當收到Request就先等待10秒再進行後續
   await Task.Delay(10000);

   return Enumerable.Range(1, 5).Select(index => new WeatherForecast
   {
      Date = DateTime.Now.AddDays(index),
      TemperatureC = Random.Shared.Next(-20, 55),
      Summary = Summaries[Random.Shared.Next(Summaries.Length)]
   })
   .ToArray();
}

在同樣Controller新增第二支API

[HttpPost(Name = "PostSecondApi")]
public ActionResult Post(
   [FromQuery] string name
)
{
   return Ok($"Hello {name} !!!");
}

相關參考

  1. 筆記Demo程式碼 - jyu.demo.HttpClientFactory
  2. 在 ASP.NET Core 中使用 IHttpClientFactory 發出 HTTP 要求
  3. 使用 HttpClientFactory 實作復原 HTTP 要求
  4. 把HttpClient換成IHttpClientFactory之後,放心多了
  5. 幾種使用IHttpClientFactory方法