利用IHttpClientFactory可以无缝创建HttpClient实例,避免手动管理它们的生命周期。

当使用ASP.Net Core开发应用程序时,可能经常需要通过HttpClient调用WebAPI的方法以检查终结点是否正常工作。要实现这一点,通常需要实例化HttpClient并使用该实例来调用你的方法。但是直接使用HttpClient也有一些缺点,主要与手动管理实例的生命周期有关。

你可以使用IHttpClientFactory创建HttpClient来避免这些问题。IHttpClientFactory是在.Net Core 2.1引入的,它提供了一个命名,配置和创建HttpClient实例的核心功能,并能自动管理实例的池化和生命周期。

下面我们通过代码进一步讨论HttpClient和IHttpClientFactory,以及所设计的概念。要使用提供的代码,你需要安装Visual Studio 2019。

在Visual Studio 2019中创建一个ASP.NET Core MVC项目

假设你的系统中安装了Visual Studio 2019,请按照下面列出来的步骤创建一个新的ASP.NET Core项目。

1. 启动Visual Studio IDE。

2. 点击“创建新项目”。

3. 在“创建新项目”窗口中,从模板列表中选择ASP.NET Core Web应用程序。

4. 单击Next。

5. 在“配置新项目”窗口中,指定新项目的名称和位置。

6. 可以选择“将解决方案和项目放在同一个目录中”复选框。

7. 点击Create。

8. 在“创建一个新的ASP.NET Core Web应用程序“窗口中,选择。NET Core作为运行时,然后选择asp.net Core作为运行时。NET Core 3.1(或更高版本)。

9. 选择“Web Application (Model-View-Controller)”作为项目模板来创建一个新的ASP.NET Core MVC应用程序。

10. 确保复选框“启用Docker支持”和“配置HTTPS”没有选中,因为我们不会在这里使用这些特性。

11. 确保身份验证设置为“无身份验证”,因为我们也不会使用身份验证。

12. 单击Create。

按照这些步骤将创建一个新的ASP.NET Core MVC应用程序。在新项目中,创建一个新的API Controller,并使用默认名称保存它,即ValuesController。我们将在接下来的部分中使用这个项目。

挑战HttpClient

尽管HttpClient没有直接实现IDisposable接口,但它扩展了System.Net.Http。HttpMessageInvoker,这个类实现了IDisposable。然而,当使用HttpClient实例时,你不应该手动操作释放它们。尽管可以在HttpClient实例上调用Dispose方法,但不推荐这样做。

应该怎么做呢?一种选择是使HttpClient静态化,或者将HttpClient的非静态实例包装在自定义类中,并使其成为单例类。但是更好的替代方法是使用IHttpClientFactory来生成HttpClient的实例,然后使用该实例来调用操作方法。

IHttpClientFactory 和HttpClientFactory

IHttpClientFactory是一个由DefaultHttpClientFactory类实现的接口,这是一个工厂模式。DefaultHttpClientFactory实现了IHttpClientFactory和IHttpMessageHandlerFactory接口。IHttpClientFactory提供了ASP.NET Core对创建、缓存和处理HttpClient实例提供了出色的内置支持。

请注意,HttpClientFactory只是一个帮助类,用于创建使用提供的处理程序配置的HttpClient实例。这个类有以下方法:

Create(DelegatingHandler[])
Create(HttpMessageHandler,DelegatingHandler[])
CreatePipeline(HttpMessageHandler,IEnumerable<DelegatingHandler>)

重载的HttpClientFactory类的Create方法看起来像这样:

public static HttpClient Create(params DelegatingHandler[] handlers)
{
return Create(new HttpClientHandler(), handlers);
}
public static HttpClient Create(HttpMessageHandler innerHandler, params DelegatingHandler[] handlers)
{
HttpMessageHandler pipeline = CreatePipeline(innerHandler, handlers);
return new HttpClient(pipeline);
}

引入HttpClientFactory和IHttpClientFactory是为了更好地管理HttpMessageHandler实例的生命周期。

为什么使用IHttpClientFactory?

当你释放HttpClient实例时,连接将保持打开状态长达4分钟。此外,可以在任何时间点打开socket的数量是有限制的——不能同时打开太多socket。因此,当使用太多HttpClient实例时,可能会耗尽socket。

这就是IHttpClientFactory的意义所在。你可以通过利用IHttpClientFactory来创建用于调用HTTP API方法的HttpClient实例,以避免HttpClient所面临的问题。在ASP.NET Core中实现IHttpClientFactory的主要目标是为了确保使用工厂模式创建HttpClient实例的同时避免socket耗尽。

在ASP.NET Core中注册IHttpClientFactory实例

你可以在Startup类的ConfigureServices方法中,通过调用IServiceCollection实例上的AddHttpClient扩展方法注册一个IHttpClientFactory类型的实例,如下:

public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddHttpClient();
}

将IHttpClientFactory实例注入到控制器

可以通过如下代码将将IHttpClientFactory实例注入到控制器:

public class HomeController : Controller
{
private IHttpClientFactory _httpClientFactory;
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger,
IHttpClientFactory httpClientFactory)
{
_logger = logger;
_httpClientFactory = httpClientFactory;
}
}

在Action中调用HttpClient

要通过使用IHttpClientFactory创建HttpClient,应该调用CreateClient方法。一旦HttpClient实例可用,就可以在HomeController类的index方法中使用以下代码来调用ValuesController类的Get方法。

public async Task<IActionResult> Index()
{
HttpClient httpClient = _httpClientFactory.CreateClient();
httpClient.BaseAddress = new Uri("http://localhost:1810/");
var response = await httpClient.GetAsync("/api/values");
string str = await response.Content.ReadAsStringAsync();
List<string> data = JsonSerializer.Deserialize<List<string>>(str);
return View(data);
}

使用IHttpClientFactory在ASP.NET Core中创建和管理HttpClient实例

有几种方法可以在应用程序中使用IHttpClientFactory。这包括直接使用IHttpClientFactory、使用命名client和类型client。

基本的或一般的使用模式,即直接使用IHttpClientFactory—在前面的小节中已经讨论过了。请参考“注册一个IHttpClientFactory实例”一节,该节讨论了如何注册HttpClient实例。

如果你想使用不同配置的HttpClient实例,以下是一个不错的选择。下面的代码片段说明了如何创建。

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", "This is a test user agent");
});

第二种方法是使用包装了HttpClient实例的自定义类,该自定义类封装了通过HTTP协议调用所有终结点的逻辑。下面的代码片段说明了如何定义自定义HttpClient类。

public class ProductService : IProductService
{
private IHttpClientFactory _httpClientFactory;
private readonly HttpClient _httpClient;
private readonly string _baseUrl = "http://localhost:1810/";
public ProductService(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<Catalog> GetAllProducts()
{
_httpClient = _httpClientFactory.CreateClient();
_httpClient.BaseAddress = new Uri(_baseUrl);
var uri = "/api/products";
var result = await _httpClient.GetStringAsync(uri);
return JsonConvert.DeserializeObject<Product>(result);
}
}

通过以下代码注册自定义的client:

services.AddHttpClient<IProductService, ProductService>();

将MessageHandler添加到命名管道中

MessageHandler是扩展自HttpMessageHandler类,它可以接受HTTP请求并返回HTTP响应。如果你想构建自己的MessageHandler,你应该创建一个继承DelegatingHandler的类。

你可以将HttpMessageHandler添加到请求处理管道中。可以在Startup类的ConfigureServices方法中使用以下代码将HttpMessageHandler添加到管道中。

public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient("github", c =>
{
c.BaseAddress = new Uri("https://api.github.com/");
})
.AddHttpMessageHandler<DemoHandler>();
services.AddTransient<DemoHandler>();
}

IHttpClientFactory是一个自.net Core 2.1以来就可用的工厂类。如果你使用IHttpClientFactory来创建HttpClient实例,那么底层HttpClientMessagehandler实例的池化和生命周期将自动管理。IHttpClientFactory还负责处理一些常见问题,比如日志记录。

原文链接:https://www.infoworld.com/article/3586176/how-to-use-ihttpclientfactory-in-aspnet-core.html

如何在ASP.NET Core 中使用IHttpClientFactory的更多相关文章

  1. 如何在ASP.NET Core中实现CORS跨域

    注:下载本文的完整代码示例请访问 > How to enable CORS(Cross-origin resource sharing) in ASP.NET Core 如何在ASP.NET C ...

  2. 如何在ASP.NET Core中实现一个基础的身份认证

    注:本文提到的代码示例下载地址> How to achieve a basic authorization in ASP.NET Core 如何在ASP.NET Core中实现一个基础的身份认证 ...

  3. 如何在ASP.NET Core中应用Entity Framework

    注:本文提到的代码示例下载地址> How to using Entity Framework DB first in ASP.NET Core 如何在ASP.NET Core中应用Entity ...

  4. [转]如何在ASP.NET Core中实现一个基础的身份认证

    本文转自:http://www.cnblogs.com/onecodeonescript/p/6015512.html 注:本文提到的代码示例下载地址> How to achieve a bas ...

  5. 如何在ASP.NET Core中使用Azure Service Bus Queue

    原文:USING AZURE SERVICE BUS QUEUES WITH ASP.NET CORE SERVICES 作者:damienbod 译文:如何在ASP.NET Core中使用Azure ...

  6. 如何在ASP.NET Core中自定义Azure Storage File Provider

    文章标题:如何在ASP.NET Core中自定义Azure Storage File Provider 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p ...

  7. 如何在ASP.NET Core中使用JSON Patch

    原文: JSON Patch With ASP.NET Core 作者:.NET Core Tutorials 译文:如何在ASP.NET Core中使用JSON Patch 地址:https://w ...

  8. [翻译] 如何在 ASP.Net Core 中使用 Consul 来存储配置

    [翻译] 如何在 ASP.Net Core 中使用 Consul 来存储配置 原文: USING CONSUL FOR STORING THE CONFIGURATION IN ASP.NET COR ...

  9. (6)ASP.NET Core 中使用IHttpClientFactory发出HTTP请求

    1.HttpClient类使用存在的问题 HttpClient类的使用所存在的问题,百度搜索的文章一大堆,好多都是单纯文字描述,让人感觉不太好理解,为了更好理解HttpClient使用存在的问题,下面 ...

随机推荐

  1. jQuery 点击input框标题收起

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  2. 阿里云ECS hadoop+spark+zookeeper+hive code-server 集群搭建

    懒得重新排版然后发到博客了.用在线文档看吧 https://www.kdocs.cn/l/srV6o8rABW9V 用线上IDE(code-server)写scala的时候,出现BUG可以参考下面两篇 ...

  3. office提示“应用程序无法正常启动(0xc0000142)。请单击确认关闭应用程序”

    打开word文档,突然弹出如下提示框: 网上查询,说应用程序无法正常启动(0xc0000142)的原因可能是缺少组件导致的.控制面板 - 时钟和区域 - 更改日期.时间或数字格式 - 管理 - 更改系 ...

  4. 四:SpringBoot-定时任务和异步任务的使用方式

    SpringBoot-定时任务和异步任务的使用方式 1.定时任务 2.同步和异步 3.定时器的使用 3.1 定时器执行规则注解 3.2 定义时间打印定时器 3.3 启动类开启定时器注解 4.异步任务 ...

  5. Django(ORM单表操作)

    默认使用sqllite数据库 修改为mysql数据库 创建数据库 在app models中编写创建数据库类 from django.db import models class Book(models ...

  6. ubuntu下scala下载+集成IDEA开发环境

    环境须知: ubuntu 16.04 scala 2.11.0 jdk 1.8.0 Idea 2016.3 JDK环境安装 (1)安装jdk, 注意scala很好的支持jdk 1.8 的jvm 编译环 ...

  7. 2.二层常用技术-Portfast和BPDU Guard、BPDU Filter

    PortFast (生成树端口加速) 1.在交换机上使用portfast命令,可以防止出现由于STP的收敛时间太长,导致主机的DHCP请求超时,从而使主机不能接收到DHCP地址的问题. 确保有一台服务 ...

  8. HTML定位

    定位(position) 定位是一种更加高级的布局手段,通过定位可以将元素摆放到元素的任何位置 使用position属性来设置定位 可选值:static 默认值,元素是静止的没有开启定位 relati ...

  9. 2019牛客暑期多校训练营(第五场)I.three points 1(暴力几何)

    题意:现在给你一个矩形边框 一个三角形的三边长 现在问你能否把三角形放入矩阵边框中 并且输出三个点的坐标 思路:我们可以发现如果一定有解 我们就可以让一个点在左下角(0,0)处 还有一个点在矩形边上 ...

  10. 2019牛客暑期多校训练营(第二场)A Eddy Walker(打表求概率)

    题意:给你n,m分别表示 长度为n的环 和最后走到的位置m 问从0点出发每次都能能往前或者往后走 求最后在m点的概率思路:我们可以先打表模拟一下 发现好像每个点的概率大概都是1/(n-1) 打表代码: ...