千家信息网

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

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,今天小编给大家分享一下ASP.NET Core怎么使用IHttpClientFactory发出HTTP请求的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参
千家信息网最后更新 2026年11月02日ASP.NET Core怎么使用IHttpClientFactory发出HTTP请求

今天小编给大家分享一下ASP.NET Core怎么使用IHttpClientFactory发出HTTP请求的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

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");        Console.ReadKey();    }    static async Task GetAsync()    {        for (int i = 0; i < 5; i++)        {            using (var client = new HttpClient())            {                var result = await client.GetAsync("http://aspnetmonsters.com/");                Console.WriteLine(result.StatusCode);            }        }    }}

输出结果:

控制台打印出五条请求站点返回状态的信息,下面我们通过netstat工具打印出五个请求连接套接字状态:

应用程序已经运行结束了(结束连接),但是打印结果显示连接状态仍然是TIME_WAIT,也就是说在此状态期间仍然在观察是否有数据包进入连接(如果连接等待中有任何数据包仍然会通过),因为它们可能在某个地方被网络延迟。

Windows将在此状态下保持连接240秒(由其设置[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\TcpTimedWaitDelay])。Windows可以快速打开新套接字的速度有限,因此如果您耗尽连接池,那么您可能会看到如下错误:

而怎么做才可以减少套接字的浪费呢?我们在上述代码中把每次循环中创建的HttpClient对象拉到Main外定义为一个共享的静态实例:

class Program{    private static HttpClient client = new HttpClient();    static void Main(string[] args)    {        Console.WriteLine("Starting connections");        var g = GetAsync();        g.Wait();        Console.WriteLine("Connections done");        Console.ReadKey();    }    static async Task GetAsync()    {        for (int i = 0; i < 5; i++)        {            var result = await client.GetAsync("http://aspnetmonsters.com/");            Console.WriteLine(result.StatusCode);        }    }}

应用程序运动完毕之后,我们再通过netstat工具打印出五个请求连接套接字状态,这时候会看到信息如下:

通过共享一个实例,减少了套接字的浪费,实际上由于套接字重用而传输快一点。
总结:

  • 在创建HttpClient实例的时候,最好是静态(static )实例。

  • 不要用using包装HttpClient对象。

在.NET Core 2.1版本之后引入的 HttpClientFactory解决了HttpClient的所有痛点。有了 HttpClientFactory,我们不需要关心如何创建HttpClient,又如何释放它。通过它可以创建具有特定业务的HttpClient,而且可以很友好的和 DI 容器结合使用,更为灵活。下面以 ASP.NET Core为例介绍HttpClientFactory的四种使用方式。

2.HttpClientFactory 的多种使用方式

可以通过多种使用方式在应用程序中使用HttpClientFactory。

2.1使用基本用法

在Startup.ConfigureServices方法中,通过在IServiceCollection上调用AddHttpClient扩展方法可以注册IHttpClientFactory服务。
services.AddHttpClient();
注册服务后,我们新建BasicUsageModel类使用IHttpClientFactory创建HttpClient实例:

public class BasicUsageModel{    private readonly IHttpClientFactory _clientFactory;    public IEnumerable Branches { get; private set; }    public bool GetBranchesError { get; private set; }    public BasicUsageModel(IHttpClientFactory clientFactory)    {        _clientFactory = clientFactory;    }    public async Task OnGet()    {        var request = new HttpRequestMessage(HttpMethod.Get,            "https://api.github.com/repos/aspnet/AspNetCore.Docs/branches");        request.Headers.Add("Accept", "application/vnd.github.v3+json");        request.Headers.Add("User-Agent", "HttpClientFactory-Sample");        var client = _clientFactory.CreateClient();        var response = await client.SendAsync(request);        if (response.IsSuccessStatusCode)        {            Branches = await response.Content                .ReadAsAsync>();        }        else        {            GetBranchesError = true;            Branches = Array.Empty();        }    }}public class GitHubBranch{    public string name { get; set; }}

以这种方式直接在使用IHttpClientFactory的类中调用CreateClient方法创建HttpClient实例。然后在Controller中调用BasicUsageModel类:

public class HomeController : Controller{    private readonly IHttpClientFactory _clientFactory;    public HomeController(IHttpClientFactory clientFactory)    {        _clientFactory = clientFactory;    }    public IActionResult Index()    {        BasicUsageModel model = new BasicUsageModel(_clientFactory);        var task = model.OnGet();        task.Wait();        List 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 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>();        }        else        {            GetPullRequestsError = true;            PullRequests = Array.Empty();        }    }}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结合使用:

类型化客户端提供与命名客户端一样的功能,不需要将字符串用作密钥。它们提供单个地址来配置特定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> 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>();        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();

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

public class TypedClientModel : PageModel{    private readonly GitHubService _gitHubService;    public IEnumerable 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();        }    }}

以上就是"ASP.NET Core怎么使用IHttpClientFactory发出HTTP请求"这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注行业资讯频道。

客户 客户端 类型 方法 配置 代码 套接字 实例 状态 应用 对象 应用程序 方式 知识 程序 篇文章 问题 不同 单个 示例 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 上海卓越科技互联网 互联网科技开发公司 奇酷互联网科技公司 卓越科技(互联网 ) 亿策互联网科技 济南华为互联网科技产业总部基地 科技与互联网哪个更好 金融科技与互联网金融相同和不同 互联网科技创新服务 允成互联网科技有限公司融资 互联网在线教育科技创业 国大互联网教育科技有限公司薪资 沐思想互联网科技有限公司 每天都有哪些好的互联网科技 深圳无忧互联网科技 江苏互联网智能科技软件 广西科技产业互联网是什么 互联网领先科技活动 互联网高科技绘画 互联网科技创业有什么好项目 江苏根荣互联网科技 互联网和科技技术 互联网科技集团 有木互联网科技 伊宁互联网科技做什么的 众安科技工业互联网合作 锡山区互联网智能科技产品供应 银行科技岗属于互联网吗 科技互联网行业投资研究 上海万顺科技互联网有限公司招聘
0