ASP.NET Core使用IHttpClientFactory发出HTTP请求

2022-04-18 13:41:02

1.HttpClient类使用存在的问题

HttpClient类的使用所存在的问题,百度搜索的文章一大堆,好多都是单纯文字描述,让人感觉不太好理解,为了更好理解HttpClient使用存在的问题,下面让我们通过代码跟示例来描述。

using(var client = new HttpClient())

传统关闭连接方法如上述代码所示,但当使用using语句释放HttpClient对象的时候,套接字(socket)也不会立即释放,下面我们通过请求aspnetmonsters站点的示例来验证下:

class Program{    static void Main(string[] args)    {        Console.WriteLine("Starting connections");        var g = GetAsync();        g.Wait();        Console.WriteLine("Connections done");ndex()    {        BasicUsageModel model = new BasicUsageModel(_clientFactory);        var task = model.OnGet();        task.Wait();        List<GitHubBranch> list = model.Branches.ToList();        return View(list);    }}

2.2使用命名客户端

如果应用程序需要有许多不同的HttpClient用法(每种用法的服务配置都不同),可以视情况使用命名客户端。可以在HttpClient中注册时指定命名Startup.ConfigureServices的配置。

services.AddHttpClient("github", c =>{    c.BaseAddress = new Uri("https://api.github.com/");    // Github API versioning    c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");    // Github requires a user-agent    c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");});

上面的代码调用AddHttpClient,同时提供名称“github”。此客户端应用了一些默认配置,也就是需要基址和两个标头来使用GitHub API。每次调用CreateClient时,都会创建HttpClient 的新实例,并调用配置操作。要使用命名客户端,可将字符串参数传递到CreateClient。指定要创建的客户端的名称:

public class NamedClientModel : PageModel{    private readonly IHttpClientFactory _clientFactory;    public IEnumerable<GitHubPullRequest> PullRequests { get; private set; }    public bool GetPullRequestsError { get; private set; }    public bool HasPullRequests => PullRequests.Any();    public NamedClientModel(IHttpClientFactory clientFactory)    {        _clientFactory = clientFactory;    }    public async Task OnGet()    {        var request = new HttpRequestMessage(HttpMethod.Get,            "repos/aspnet/AspNetCore.Docs/pulls");        var client = _clientFactory.CreateClient("github");        var response = await client.SendAsync(request);        if (response.IsSuccessStatusCode)        {            PullRequests = await response.Content                .ReadAsAsync<IEnumerable<GitHubPullRequest>>();        }        else        {            GetPullRequestsError = true;            PullRequests = Array.Empty<GitHubPullRequest>();        }    }}public class GitHubPullRequest{    public string url { get; set; }    public int? id { get; set; }    public string node_id { get; set; }}

在上述代码中,请求不需要指定主机名。可以仅传递路径,因为采用了为客户端配置的基址。在Controller中调用方法如上个示例。

2.3使用类型化客户端

什么是“类型化客户端”?它只是DefaultHttpClientFactory注入时配置的HttpClient。
下图显示了如何将类型化客户端与HttpClientFactory结合使用:

ASP.NET Core使用IHttpClientFactory发出HTTP请求

类型化客户端提供与命名客户端一样的功能,不需要将字符串用作密钥。它们提供单个地址来配置特定HttpClient并与其进行交互。例如,单个类型化客户端可能用于单个后端终结点,并封装此终结点的所有处理逻辑。另一个优势是它们使用 DI 且可以被注入到应用中需要的位置。
类型化客户端在构造函数中接收HttpClient参数:

public class GitHubService{    public HttpClient Client { get; }    public GitHubService(HttpClient client)    {        client.BaseAddress = new Uri("https://api.github.com/");        // GitHub API versioning        client.DefaultRequestHeaders.Add("Accept",            "application/vnd.github.v3+json");        // GitHub requires a user-agent        client.DefaultRequestHeaders.Add("User-Agent",            "HttpClientFactory-Sample");        Client = client;    }    public async Task<IEnumerable<GitHubIssue>> GetAspNetDocsIssues()    {        var response = await Client.GetAsync("/repos/aspnet/AspNetCore.Docs/issues?state=open&sort=created&direction=desc");        response.EnsureSuccessStatusCode();        var result = await response.Content            .ReadAsAsync<IEnumerable<GitHubIssue>>();        return result;    }}public class GitHubIssue{    public string url { get; set; }    public int? id { get; set; }    public string node_id { get; set; }}

在上述代码中,配置转移到了类型化客户端中。HttpClient对象公开为公共属性。可以定义公开HttpClient功能的特定于API的方法。GetAspNetDocsIssues方法从GitHub存储库封装查询和分析最新待解决问题所需的代码。
要注册类型化客户端,可在Startup.ConfigureServices中使用通用的AddHttpClient扩展方法,指定类型化客户端类:

services.AddHttpClient<GitHubService>();

使用DI将类型客户端注册为暂时客户端。可以直接插入或使用类型化客户端:

public class TypedClientModel : PageModel{    private readonly GitHubService _gitHubService;    public IEnumerable<GitHubIssue> LatestIssues { get; private set; }    public bool HasIssue => LatestIssues.Any();    public bool GetIssuesError { get; private set; }    public TypedClientModel(GitHubService gitHubService)    {        _gitHubService = gitHubService;    }    public async Task OnGet()    {        try        {            LatestIssues = await _gitHubService.GetAspNetDocsIssues();        }        catch (HttpRequestException)        {            GetIssuesError = true;            LatestIssues = Array.Empty<GitHubIssue>();        }    }}

到此这篇关于ASP.NET Core使用IHttpClientFactory发出HTTP请求的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。