分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 软件开发

ASP.NET Core 2.2 基础知识(十二) 发送 HTTP 请求

发布时间:2023-09-06 02:29责任编辑:苏小强关键词:.NET
原文:ASP.NET Core 2.2 基础知识(十二) 发送 HTTP 请求

可以注册 IHttpClientFactory 并将其用于配置和创建应用中的 HttpClient 实例。 这能带来以下好处:

  • 提供一个中心位置,用于命名和配置逻辑 HttpClient 实例。 例如,可以注册 github 客户端,并将它配置为访问 GitHub。 可以注册一个默认客户端用于其他用途。
  • 通过委托 HttpClient 中的处理程序整理出站中间件的概念,并提供适用于基于 Polly 的中间件的扩展来利用概念。
  • 管理基础 HttpClientMessageHandler 实例的池和生存期,避免在手动管理 HttpClient 生存期时出现常见的 DNS 问题。
  • (通过 ILogger)添加可配置的记录体验,以处理工厂创建的客户端发送的所有请求。

在应用中可以通过以下多种方式使用 IHttpClientFactory

基本用法

 ???????public void ConfigureServices(IServiceCollection services) ???????{ ???????????services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); ???????????services.AddHttpClient(); ???????}
 ???[Route("api/[controller]")] ???[ApiController] ???public class ValuesController : ControllerBase ???{ ???????private readonly IHttpClientFactory _clientFactory; ???????public ValuesController(IHttpClientFactory clientFactory) ???????{ ???????????_clientFactory = clientFactory; ???????} ???????// GET api/values ???????[HttpGet] ???????public async Task<string> Get() ???????{ ???????????HttpClient client = _clientFactory.CreateClient(); ???????????//方法一: ???????????//HttpRequestMessage request = new HttpRequestMessage ???????????//{ ???????????// ???Method = new HttpMethod("get"), ???????????// ???RequestUri = new System.Uri("http://localhost:5000/api/values"), ???????????//}; ???????????//HttpResponseMessage response = await client.SendAsync(request); ???????????//string res = await response.Content.ReadAsStringAsync(); ???????????//return res; ???????????//方法二: ???????????string res = await client.GetStringAsync("http://localhost:5000/api/values"); ???????????return res; ???????} ????}

命名客户端

 ???????public void ConfigureServices(IServiceCollection services) ???????{ ???????????services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); ???????????services.AddHttpClient("test", c => ???????????{ ???????????????c.BaseAddress = new Uri("http://localhost:5000"); ???????????}); ???????}
 ???????public async Task<string> Get() ???????{ ???????????HttpClient client = _clientFactory.CreateClient("test"); ???????????//注册名叫 "test" 的客户端时,已经指定了该客户端的请求基地址,所以这里不需要指定主机名了 ???????????return await client.GetStringAsync("api/values"); ???????}

类型化客户端

 ???public class TestHttpClient ???{ ???????public HttpClient Client { get; set; } ???????public TestHttpClient(HttpClient client) ???????{ ???????????client.BaseAddress = new System.Uri("http://localhost:5000"); ???????????Client = client; ???????} ???????public async Task<string> Get() ???????{ ???????????return await Client.GetStringAsync("api/values"); ???????} ???}
 ???????public void ConfigureServices(IServiceCollection services) ???????{ ???????????services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); ???????????services.AddHttpClient<TestHttpClient>(c => ???????????{ ???????????????//可以在这里设置,也可以在构造函数设置. ???????????????//c.BaseAddress = new System.Uri("http://localhost:5000"); ???????????}); ???????}
 ???[Route("api/[controller]")] ???[ApiController] ???public class ValuesController : ControllerBase ???{ ???????private readonly TestHttpClient _client; ???????public ValuesController(TestHttpClient client) ???????{ ???????????_client = client; ???????} ????????????[HttpGet] ???????public async Task<string> Get() ???????{ ???????????return await _client.Get(); ???????} ???}

出站请求中间件

HttpClient 已经具有委托处理程序的概念,这些委托处理程序可以链接在一起,处理出站 HTTP 请求。 IHttpClientFactory 可以轻松定义处理程序并应用于每个命名客户端。 它支持注册和链接多个处理程序,以生成出站请求中间件管道。 每个处理程序都可以在出站请求前后执行工作。 此模式类似于 ASP.NET Core 中的入站中间件管道。 它提供了一种用于管理围绕 HTTP 请求的横切关注点的机制,包括缓存、错误处理、序列化以及日志记录。

要创建处理程序,需要定义一个派生自 DelegatingHandler 的类。 重写 SendAsync 方法,在将请求传递至管道中的下一个处理程序之前执行代码:

 ???public class ValidateHeaderHandler : DelegatingHandler ???{ ???????protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) ???????{ ???????????if (!request.Headers.Contains("refuge")) ???????????{ ???????????????return new HttpResponseMessage(HttpStatusCode.BadRequest) ???????????????{ ???????????????????Content = new StringContent("not found refuge") ???????????????}; ???????????} ???????????return await base.SendAsync(request, cancellationToken); ???????} ???}
 ???????public void ConfigureServices(IServiceCollection services) ???????{ ???????????services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); ???????????services.AddTransient<ValidateHeaderHandler>();//生存期必须是临时 ???????????services.AddHttpClient("test", c => ???????????????{ ???????????????????c.BaseAddress = new Uri("http://localhost:5000"); ???????????????}) ???????????????.AddHttpMessageHandler<ValidateHeaderHandler>(); ???????}

HttpClient 和生存期管理

每次对 IHttpClientFactory 调用 CreateClient 都会返回一个新 HttpClient 实例:

 ???????public IEnumerable<int> Get() ???????{ ???????????//测试生存期 ???????????for (int i = 0; i < 4; i++) ???????????{ ???????????????HttpClient client = i % 2 == 0 ???????????????????? _clientFactory.CreateClient("test") ???????????????????: _clientFactory.CreateClient(); ???????????????yield return client.GetHashCode(); ???????????} ???????}

CreateClient 方法内部会调用 CreateHandler 方法,后者创建 HttpMessageHandler,

源码如下:

 ???public HttpClient CreateClient(string name) ???{ ?????if (name == null) ???????throw new ArgumentNullException(nameof (name)); ?????HttpClient httpClient = new HttpClient(this.CreateHandler(name), false); ?????HttpClientFactoryOptions clientFactoryOptions = this._optionsMonitor.Get(name); ?????for (int index = 0; index < clientFactoryOptions.HttpClientActions.Count; ++index) ???????clientFactoryOptions.HttpClientActions[index](httpClient); ?????return httpClient; ???}
 ???public HttpMessageHandler CreateHandler(string name) ???{ ?????if (name == null) ???????throw new ArgumentNullException(nameof (name)); ?????ActiveHandlerTrackingEntry entry = this._activeHandlers.GetOrAdd(name, this._entryFactory).Value; ?????this.StartHandlerEntryTimer(entry); ?????return (HttpMessageHandler) entry.Handler; ???}

而这个 _activeHandlers 的类型是 : 

一个线程安全的键值对集合.

因此,实际上创建的 HttpMessageHandler 实例会汇集到池中.新建 HttpClient 实例时,可能会重用池中的 HttpMessageHandler 实例(如果生存期尚未到期的话). 

由于每个处理程序通常管理自己的基础 HTTP 连接,因此需要池化处理程序.创建超出必要数量的处理程序可能会导致连接延迟. 部分处理程序还保持连接无期限地打开,这样可以防止处理程序对 DNS 更改作出反应.

处理程序的默认生存期为两分钟,可在每个命名客户端上重写默认值:

services.AddHttpClient("test").SetHandlerLifetime(TimeSpan.FromMinutes(5));

配置 HttpMessageHandler

有时候,我们需要控制客户端使用的内部 HttpMessageHandler .

 ???????????services.AddHttpClient("test") ???????????????.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() ???????????????{ ???????????????????AllowAutoRedirect = false, ???????????????});

ASP.NET Core 2.2 基础知识(十二) 发送 HTTP 请求

原文地址:https://www.cnblogs.com/lonelyxmas/p/10230908.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved