此筆記為紀錄工作上碰到開發需要,使用IHttpClientFactory
來建立管控HttpClient
生命週期。
依據官方文件(相關參考2)敘述,如果單純使用HttpClient
進行Http請求,一般作法建立HttpClient
新實體,再透過此建立實體來進行Http請求動作。
正常使用完畢後,我們都會認為會自動釋放,因為該類別內部有繼承IDisposable
特性,但是,系統背後通訊端Socket資源佔用問題,卻不會隨著當下實體用完銷毀就跟著被釋放,而後還有其他關於DNS異動調整問題,可以參考相關連結了解詳細。
根據上述狀況,使用官方推薦以IHttpClientFactory
方式來進行HttpClient
管控,在此筆記紀錄基本用法與單一實體在生命週期內重複利用。
Microsoft.Extensions.DependencyInjection
Microsoft.Extensions.Http
ServiceCollection serviceCollection = new ServiceCollection();
serviceCollection.AddHttpClient();
var serviceBuilder = serviceCollection.BuildServiceProvider();
var httpClientFactory = serviceBuilder.GetService<IHttpClientFactory>();
依據註入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請求行為如下
TaskCanceledException
。TaskCanceledException
發生,進行呼叫第二支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} !!!");
}