为了更方便在服务端调用 HTTP 请求,微软在 .NET Framework 4.x 的时候引入了 HttpClient。但 HttpClient 有很多严重问题,一直饱受诟病,比如 InfoQ 的这篇文章 t.cn/Evzy80y,吐槽了 HttpClient 不能立即关闭连接、性能消耗严重等的问题。

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

一、直接使用方式

不管是哪种方式,都要先注册服务,对于 ASP.NET Core 应用则是在 Startup.cs 文件的 ConfigureServices 添加如果代码:

services.AddHttpClient();

然后在 Controller 中通过构造注入的试获得 IHttpClientFactory,然后通过它来创建 HttpClient 对象。示例代码:

public class ValuesController : BaseController
{
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);
}
}

这种使用方式适合一次性的 HTTP 请求调用,弊端是如果多次都要请求 github 的接口,那就得写很多重复代码配置 HttpClient。

二、命名式使用方式

命名式的使用方式可以解决第一种方式的问题,对于特定域名的 HTTP 调用,可以只做一次配置,然后在多个地方通过名称拿到相同的 Client 来使用。

首先在 Startup.cs 注册服务的地方添加带有特定名称的 HttpClient 服务,并添加需要的配置,如下示例:

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,一次是没有命名的,一次是有命名的。在 Controller 中的使用方式是:

public class ValuesController : BaseController
{
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);
}
}

但如果使用很频繁,这种获取 Client 的方式还是有一点麻烦。下面介绍第三种方式,可以在使用的时候方便一点,但配置要麻烦些。

三、类型化使用方式

类型化的使用方式可以预先把配置放到自定义的 HttpClient 中,然后在需要的地方都过依赖注入直接拿到 HttpClient 实例。

我们来看具体的例子,首先自定义一个 HttClient 类,比如访问 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;
} public async Task<string> GetData()
{
return await _client.GetStringAsync("/");
}
}

这里的 GetData 就是额外扩展的共用方法。使用前需要为这个类注册服务:

services.AddHttpClient<GitHubClient>();

然后在需要的地方(比如 Controller)中这样使用:

public class ValuesController : BaseController
{
private readonly GitHubClient _gitHubClient;; public ValuesController(GitHubClient gitHubClient)
{
_gitHubClient = gitHubClient;
} [HttpGet]
public async Task<ActionResult> Get()
{
string result = await _gitHubClient.GetData();
return Ok(result);
}
}

类型化的方式和命名式的方式相比,虽然在配置的时候会麻烦一点,但它有两个好处:一是不用通过名称字符串来获得 Client,而是直接通过依赖注入获得具体的 Client;二是可以在自定义的 HttpClient 类中扩展共用的方法。

.NET Core 中正确使用 HttpClient 的姿势的更多相关文章

  1. iOS中正确的截屏姿势

    昨天写了个用到截屏功能的插件,结果问题不断,今天终于解决好了,把debug过程中所有尝试过的截屏方法都贴出来吧- 第一种 这是iOS 3时代开始就被使用的方法,它被废止于iOS 7.iOS的私有方法, ...

  2. .NET Core 中读取 Request.Headers 的姿势

    Request.Headers 的类型是 IHeaderDictionary 接口,对应的实现类是 HeaderDictionary ,C# 实现源码见 HeaderDictionary.cs . H ...

  3. 在 .NET Core 中结合 HttpClientFactory 使用 Polly(下篇)

    译者:王亮作者:Polly 团队原文:http://t.cn/EhZ90oq声明:我翻译技术文章不是逐句翻译的,而是根据我自己的理解来表述的(包括标题).其中可能会去除一些不影响理解但本人实在不知道如 ...

  4. 在 .NET Core 中结合 HttpClientFactory 使用 Polly(中篇)

    译者:王亮作者:Polly 团队原文:http://t.cn/EhZ90oq声明:我翻译技术文章不是逐句翻译的,而是根据我自己的理解来表述的(包括标题).其中可能会去除一些不影响理解但本人实在不知道如 ...

  5. 在 .NET Core 中结合 HttpClientFactory 使用 Polly(上篇)

    译者:王亮作者:Polly 团队原文:http://t.cn/EhZ90oq 译者序一:前两天写了一篇文章 .NET Core 开源项目 Polly 介绍,在写这篇文章查看 Polly 资料时,看到了 ...

  6. ASP.NET Core中如何针对一个使用HttpClient对象的类编写单元测试

    原文地址: How to unit test a class that consumes an HttpClient with IHttpClientFactory in ASP.NET Core? ...

  7. HttpClient在.NET Core中的正确打开方式

    问题来源 长期以来,.NET开发者都通过下面的方式发送http请求: using (var httpClient = new HttpClient()) { var response = await ...

  8. ASP.NET Core 中读取 Request.Body 的正确姿势

    ASP.NET Core 中的 Request.Body 虽然是一个 Stream ,但它是一个与众不同的 Stream —— 不允许 Request.Body.Position=0 ,这就意味着只能 ...

  9. Asp.Net Core 单元测试正确姿势

    背景 ASP.NET Core 支持依赖关系注入 (DI) 软件设计模式,并且默认注入了很多服务,具体可以参考 官方文档, 相信只要使用过依赖注入框架的同学,都会对此有不同深入的理解,在此无需赘言. ...

随机推荐

  1. Python笔记(十五):匿名函数和@property

    (一)匿名函数 不想显式定义函数的时候,可以使用匿名函数. def f(x): return x*x #将匿名函数赋值给一个变量 result = lambda x:x*x print(result( ...

  2. python 画个小猪佩奇

    不知道大家小时候有没有学习过logo语言,就是操纵一只小王八,来画各种图案.博主小学微机课就学习了这个,最近发现python的turtle包就是logo语言,所以画个小猪佩奇和大家分享. 代码来自知乎 ...

  3. Percona XtraBackup 安装介绍篇

    XtraBackup介绍 XtraBackup是Percona公司的开源项目,用以实现类似Innodb官方的热备份工具InnoDB Hot Backup的功能,它支持在线热备份(备份时不影响数据读写) ...

  4. Oracle EBS R12 GL_IMPORT_REFERENCES 映射

    非原创. 转自出处: http://alloracleapps.com/oracle_apps/gl_import_references-columns-mapping-11i-vs-r12/

  5. sql 重复数据查询

    具体代码: ); ORDER BY tcount DESC;

  6. Jmeter 登入、新增、查询、修改、删除,动态传参。

    1.设置HTTP Request Defaults    请求默认值,这样之后每次请求同一个域名端口的时候后都不用输入协议.域名.端口号. 2.输入[登入]的接口号. 3.设置HTTP header  ...

  7. kafka_2.11-2.0.0_介绍

    1. JMS是什么 1.1. JMS的基础 JMS是什么:JMS是Java提供的一套技术规范 JMS干什么用:用来异构系统 集成通信,缓解系统瓶颈,提高系统的伸缩性增强系统用户体验,使得系统模块化和组 ...

  8. 基于WIN8.1:新手篇→tomcat安装配置

    一.JDK配置 下载安装JDK和tomcat 打开电脑属性,高级系统设置进行环境变量配置 新建系统变量,变量值为JDK安装路径,并在系统变量path最后加上“%JAVA_HOME%\bin;%JAVA ...

  9. March 09th, 2018 Week 10th Friday

    All good things must come to an end. 好景无常. Love is when the other person's happiness is more importa ...

  10. html + js 实现图片上传,压缩,预览及图片压缩后得到Blob对象继续上传问题

    先上效果 上传图片后(设置了最多上传3张图片,三张后上传按钮消失) 点击图片放大,可以使用删除和旋转按钮 (旋转功能主要是因为ios手机拍照后上传会有写图片被自动旋转,通过旋转功能可以调正) html ...