[英]Best Practice for Use HttpClient
我正在使用 HttpClient 向 WebApi 發出請求。
我已經寫了這段代碼
public async Task<string> ExecuteGetHttp(string url, Dictionary<string, string> headers = null)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
if (headers != null)
{
foreach (var header in headers)
{
client.DefaultRequestHeaders.Add(header.Key, header.Value);
}
}
var response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}
現在我從我的動作中調用這個方法。
public async Task<ActionResult> Index()
{
try
{
RestWebRequest RestWebRequest = new RestWebRequest();
Dictionary<string, string> headers = new Dictionary<string, string>();
headers.Add("Authorization", "bearer _AxE9GWUO__8iIGS8stK1GrXuCXuz0xJ8Ba_nR1W2AhhOWy9r98e2_YquUmjFsAv1RcI94ROKEbiEjFVGmoiqmUU7qB5_Rjw1Z3FWMtzEc8BeM60WuIuF2fx_Y2FNTE_6XRhXce75MNf4-i0HbygnClzqDdrdG_B0hK6u2H7rtpBFV0BYZIUqFuJpkg4Aus85P8_Rd2KTCC5o6mHPiGxRl_yGFFTTL4_GvSuBQH39RoMqNj94A84KlE0hm99Yk-8jY6AKdxGRoEhtW_Ddow9FKWiViSuetcegzs_YWiPMN6kBFhY401ON_M_aH067ciIu6nZ7TiIkD5GHgndMvF-dYt3nAD95uLaqX6t8MS-WS2E80h7_AuaN5JZMOEOJCUi7z3zWMD2MoSwDtiB644XdmQ5DcJUXy_lli3KKaXgArJzKj85BWTAQ8xGXz3PyVo6W8swRaY5ojfnPUmUibm4A2lkRUvu7mHLGExgZ9rOsW_BbCDJq6LlYHM1BnAQ_W6LAE5P-DxMNZj7PNmEP1LKptr2RWwYt17JPRdN27OcSvZZdam6YMlBW00Dz2T2dgWqv7LvKpVhMpOtjOSdMhDzWEcf6yqr4ldVUszCQrPfjfBBtUdN_5nqcpiWlPx3JTkx438i08Ni8ph3gDQQvl3YL5psDcdwh0-QtNjEAGvBdQCwABvkbUhnIQQo_vwA68ITg07sEYgCl7Sql5IV7bD_x-yrlHyaVNtCn9C4zVr5ALIfj0YCuCyF_l1Z1MTRE7nb");
var getCategories = await RestWebRequest.ExecuteGetHttp("http://localhost:53646/api/Job/GetAllCategories?isIncludeChild=true", headers);
}
catch (HttpRequestException ex)
{
return View();
}
return View();
}
我如何為多個調用使用相同的 httpClient 對象。
讓我們假設首先我打電話
http://localhost:53646/api/Job/GetAllCategories?isIncludeChild=true
現在在同一個控制器中,我必須使用不同的標頭和不同的 url 調用另一個 Api。
http://localhost:53646/api/Job/category/10
我應該創建HttpClient
的全局對象並為所有 API 調用使用相同的對象。
在整個應用程序中僅使用一個HttpClient的挑戰在於,當您想要使用不同的憑據或嘗試更改請求的默認標頭(或傳入的HttpClientHandler中的任何內容)時。 在這種情況下,您將需要一組特定用途的 HttpClient 來重用,因為只使用一個會有問題。
我建議根據您希望發出的請求的“類型”創建一個 HttpClient 並重新使用它們。 例如,您需要的每個憑據都有一個 - 並且如果您有幾組默認標頭,則每個標頭一個。
它可能是 HttpClient 屬性(不是線程安全的)之間的一種雜耍行為,並且如果發生變化則需要它們自己的實例:
- BaseAddress
- DefaultRequestHeaders
- MaxResponseContentBufferSize
- Timeout
以及您可以傳遞給“動詞”方法(get、put、post 等)的內容。 例如,使用HttpClient.PostAsync Method (String, HttpContent)
您可以為[HttpContent][3]
指定標頭(不必將它們放在 HttpClient DefaultHeaders 中)。
HttpClient 的所有異步方法都是線程安全的(PostAsync)等。
僅僅因為你可以,並不意味着你應該。
你沒有,但你可以重用HttpClient的,例如當你想發出一個緊密循環的HTTP請求。 這節省了實例化對象所需的一小部分時間。
您的 MVC 控制器針對每個請求進行實例化。 因此,同時實例化 HttpClient 不會浪費任何大量時間。 請記住,您將使用它發出一個 HTTP 請求,這將比實例化花費更多的時間。
如果您確實堅持要重用一個實例,因為您已經對其進行了基准測試並評估了 HttpClient 的實例化是您最大的瓶頸,那么您可以查看依賴注入並將單個實例注入到每個需要它的控制器中。
在.net core 中,你可以用HttpClientFactory做同樣的事情:
public interface IBuyService
{
Task<Buy> GetBuyItems();
}
public class BuyService: IBuyService
{
private readonly HttpClient _httpClient;
public BuyService(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<Buy> GetBuyItems()
{
var uri = "Uri";
var responseString = await _httpClient.GetStringAsync(uri);
var buy = JsonConvert.DeserializeObject<Buy>(responseString);
return buy;
}
}
配置服務
services.AddHttpClient<IBuyService, BuyService>(client =>
{
client.BaseAddress = new Uri(Configuration["BaseUrl"]);
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.