Microsoft在.NET Framework 4.5中引入了HttpClient,这是在.NET服务器端代码中使用Web API最流行的方法。但是,它存在一些严重的问题,比如处理HttpClient对象不会立即关闭套接字,影响性能的实例太多,以及singleton HttpClient或共享HttpClient实例不遵守dns生存时间(ttl)设置。HttpClientfactory解决了所有这些问题。它是ASP.NET核心2.1的最新功能之一。它为在应用程序中命名、配置和使用逻辑HttpClients提供了一个中心位置,本文讨论了在ASP.NET核心2.1中使用HttpClientfactory的3种方法。
有三种不同的使用方法,我们将看到每种方法的示例。
直接使用httpclientfactory
不管您选择上面提到的方式如何,您都必须在startup.cs类的configureServices方法中注册httpclient。以下代码行注册没有特殊配置的httpclient。
services.AddHttpClient();
您可以在API控制器中按以下方式使用它。
public class ValuesController : Controller
{
private readonly IHttpClientFactory _httpClientFactory;
public ValuesController(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
[HttpGet]
public async Task<ActionResult> Get()
{
var client = _httpClientFactory.CreateClient();
client.BaseAddress = new Uri("http://api.github.com");
string result = await client.GetStringAsync("/");
return Ok(result);
}
}
Named Clients
在上面的例子中,httpclientfactory的基本用法在需要从代码中的单个位置快速发出请求的情况下是理想的。当您需要从代码的多个位置发出多个请求时,“Named Clients”将帮助您。对于Named Clients,可以使用一些预配置的设置来定义HTTP客户机,这些设置将在创建http client时应用。
services.AddHttpClient();
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", "HttpClientFactory-Sample");
});
这里我们调用addhttpclient两次,一次使用“github”,另一次不使用。GitHub客户端应用了一些默认配置,即基地址和使用GitHub API所需的两个头。addhttpclient方法的重载接受两个参数,一个名称和一个操作委托接受一个httpclient,它允许我们配置httpclient。
您可以在API控制器中按以下方式使用Named Clients。
public class ValuesController : Controller
{
private readonly IHttpClientFactory _httpClientFactory;
public ValuesController(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
[HttpGet]
public async Task<ActionResult> Get()
{
var client = _httpClientFactory.CreateClient("github");
string result = await client.GetStringAsync("/");
return Ok(result);
}
}
这里,我们在createClient()方法中传递对象的名称来创建httpclient。这很有用,因为注册时定义的默认配置将在我们请求Named Clients时预先应用。
Typed Client
使用Typed Client,可以在自定义类中为httpclient定义预配置。这个自定义类可以注册为Typed Client,稍后在需要时,可以通过调用类构造函数注入。我更喜欢打字客户,原因如下:
命名客户似乎采用了灵活的方法。
您不再需要处理字符串(如命名客户机)。
您可以封装HTTP调用和处理该端点的所有逻辑。
让我们看一个例子。下面是为GitHub客户端定义的自定义类。
public class GitHubClient
{
public HttpClient Client { get; private set; }
public GitHubClient(HttpClient httpClient)
{
httpClient.BaseAddress = new Uri("https://api.github.com/");
httpClient.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
httpClient.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
Client = httpClient;
}
}
您可以使用以下行将其注册为Typed Client。
services.AddHttpClient<GitHubClient>();
并且,在API控制器中按以下方式使用它。
public class ValuesController : Controller
{
private readonly GitHubClient _gitHubClient;;
public ValuesController(GitHubClient gitHubClient)
{
_gitHubClient = gitHubClient;
}
[HttpGet]
public async Task<ActionResult> Get()
{
string result = await _gitHubClient.client.GetStringAsync("/");
return Ok(result);
}
}
这很管用。还有另一种更好的方法使Typed Client工作。这里,httpclient是直接公开的,但是您可以使用以下方法完全封装httpclient。首先,定义GithubClient。
public interface IGitHubClient
{
Task<string> GetData();
}
public class GitHubClient : IGitHubClient
{
private readonly HttpClient _client;
public GitHubClient(HttpClient httpClient)
{
httpClient.BaseAddress = new Uri("https://api.github.com/");
httpClient.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
httpClient.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
_client = httpClient;
}
public async Task<string> GetData()
{
return await _client.GetStringAsync("/");
}
}
使用以下行将其注册为Typed Client。
services.AddHttpClient<IGitHubClient, GitHubClient>();
并且,在API控制器中按以下方式使用它。
public class ValuesController : Controller
{
private readonly IGitHubClient _gitHubClient;;
public ValuesController(IGitHubClient gitHubClient)
{
_gitHubClient = gitHubClient;
}
[HttpGet]
public async Task<ActionResult> Get()
{
string result = await _gitHubClient.GetData();
return Ok(result);
}
}
这种方法还使得单元测试变得容易,同时测试httpclients,因为您不再需要模拟它们。
总而言之,本文讨论了将httpclientFactory与ASP.NET核心2.1结合使用的所有3种可能的方法。我更喜欢使用typedclient,因为它更加灵活,为httpclient提供了封装,并使代码测试变得容易。httpclientFactory是ASP.NET核心2.1的重要补充,因为它解决了httpclient的问题。