当前位置: 首页 > ai >正文

C#.NET HttpClient 使用教程

简介

HttpClient.NET 中用于发送 HTTP 请求和接收 HTTP 响应的现代化 API,它取代了过时的 WebClientHttpWebRequest 类。

HttpClient.NET Framework 4.5 + 和 .NET Core/.NET 5+ 中提供的、基于消息处理管道(message handler pipeline)的现代 HTTP 客户端库。

相比早期的 HttpWebRequest,它更易用、支持异步、可扩展性强,并且在 .NET Core 中底层使用 SocketsHttpHandler,性能与可配置性都有显著提升。

底层架构

  • HttpClient

    • 封装请求创建、发送及响应处理逻辑,提供 GetAsync、PostAsync、SendAsync 等方法。
  • HttpMessageHandler 管道

    • 默认使用 SocketsHttpHandler(.NET Core/.NET 5+).NET Framework 下为 HttpClientHandler

    • 可以通过继承 DelegatingHandler 串联多个自定义中间件(例如日志、重试、认证)。

  • 连接池与长连接

    • SocketsHttpHandler 内置连接池和 HTTP/2 支持,同一目标主机复用 TCP 连接,减少握手与重建成本。

HttpClient 核心特性

特性说明优势
异步支持所有方法都有异步版本避免阻塞线程,提高并发能力
连接池自动管理 HTTP 连接减少 TCP 连接开销
超时控制可配置请求超时时间防止长时间阻塞
内容处理内置多种内容处理器简化 JSON/XML 处理
取消支持支持 CancellationToken优雅终止长时间请求
扩展性可通过 DelegatingHandler 扩展实现日志、重试等中间件

常用方法

使用单例
public static class HttpClientSingleton
{public static readonly HttpClient Instance = new HttpClient();
}// 使用
await HttpClientSingleton.Instance.GetAsync(url);
  • 全局唯一,避免重复创建 handler,复用连接池。

  • 需注意:设置到期(Timeout)、默认头(DefaultRequestHeaders)等全局属性变更会影响所有调用。

使用 HttpClientFactory 工厂
services.AddHttpClient("GitHub", client =>
{client.BaseAddress = new Uri("https://api.github.com/");client.DefaultRequestHeaders.Add("User-Agent", "MyApp");
})
.AddTransientHttpErrorPolicy(policy =>policy.WaitAndRetryAsync(3, _ => TimeSpan.FromSeconds(2)));// 使用
var client = _httpClientFactory.CreateClient("GitHub");
  • 框架管理生命周期、稳定重用 SocketsHttpHandler

  • 支持命名客户端、类型化客户端、配置管道、添加 Polly 弹性策略。

类型化客户端
public class GitHubService {private readonly HttpClient _client;public GitHubService(HttpClient client) => _client = client;// 封装API方法
}
// 注册
services.AddHttpClient<GitHubService>(client => { /* 配置 */ });
GET 请求
var client = HttpClientSingleton.Instance;
var response = await client.GetAsync("https://api.example.com/items/1");
response.EnsureSuccessStatusCode();
string json = await response.Content.ReadAsStringAsync();
POST 请求
var content = new StringContent(JsonSerializer.Serialize(new { Name = "测试" }),Encoding.UTF8, "application/json");
var postResp = await client.PostAsync("https://api.example.com/items", content);
postResp.EnsureSuccessStatusCode();
SendAsync 自定义请求
var request = new HttpRequestMessage(HttpMethod.Put, $"items/{id}")
{Content = new StringContent(json, Encoding.UTF8, "application/json")
};
request.Headers.Add("X-Custom", "Value");using var resp = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
resp.EnsureSuccessStatusCode();
流式上传/下载
// 下载
using var resp = await client.GetAsync(fileUrl, HttpCompletionOption.ResponseHeadersRead);
using var stream = await resp.Content.ReadAsStreamAsync();
// 将 stream 写入文件 ...// 上传
using var fs = File.OpenRead(localFilePath);
var streamContent = new StreamContent(fs);
var uploadResp = await client.PostAsync(uploadUrl, streamContent);
DelegatingHandler 管道
public class LoggingHandler : DelegatingHandler
{protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken ct){Console.WriteLine($"Request: {request}");var resp = await base.SendAsync(request, ct);Console.WriteLine($"Response: {resp}");return resp;}
}// 注册(HttpClientFactory)
services.AddHttpClient("WithLogging").AddHttpMessageHandler<LoggingHandler>();
Polly 弹性策略
services.AddHttpClient("GitHub").AddTransientHttpErrorPolicy(p =>p.WaitAndRetryAsync(3, retry => TimeSpan.FromSeconds(1)));
  • AddTransientHttpErrorPolicy 捕获 5xx、408、HttpRequestExceptiontransient 错误;

  • 可组合断路器、超时、隔离策略。

认证与配置
  • Bearer Token
client.DefaultRequestHeaders.Authorization =new AuthenticationHeaderValue("Bearer", accessToken);
  • Client Certificates
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(new X509Certificate2("cert.pfx", "pwd"));
var client = new HttpClient(handler);
  • 代理
handler.Proxy = new WebProxy("http://127.0.0.1:8888");
handler.UseProxy = true;
设置超时和请求头
httpClient.Timeout = TimeSpan.FromSeconds(30); // 设置全局超时
httpClient.DefaultRequestHeaders.Add("User-Agent", "MyApp/1.0");
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "your-token");
处理不同类型的响应
// 获取 JSON 响应
var jsonResponse = await httpClient.GetStringAsync("https://api.example.com/json");// 获取二进制响应(如文件下载)
var bytes = await httpClient.GetByteArrayAsync("https://example.com/file.pdf");// 获取流响应(大文件下载,避免内存溢出)
await using var stream = await httpClient.GetStreamAsync("https://example.com/largefile.zip");await using var fileStream = File.Create("largefile.zip");
await stream.CopyToAsync(fileStream);
发送带参数的请求
// GET 请求带查询参数
var queryParams = new Dictionary<string, string>
{{ "page", "1" },{ "size", "20" }
};
var uri = new UriBuilder("https://api.example.com/data")
{Query = new FormUrlEncodedContent(queryParams).ReadAsStringAsync().Result
};
var response = await httpClient.GetAsync(uri.Uri);// POST 请求带表单数据
var formContent = new FormUrlEncodedContent(new[]
{new KeyValuePair<string, string>("username", "test"),new KeyValuePair<string, string>("password", "pass")
});
await httpClient.PostAsync("https://example.com/login", formContent);
处理 HTTP 错误
try
{var response = await httpClient.GetAsync("https://api.example.com/resource");response.EnsureSuccessStatusCode(); // 非 200 状态码会抛出异常
}
catch (HttpRequestException ex)
{Console.WriteLine($"HTTP Error: {ex.StatusCode}");Console.WriteLine($"Message: {ex.Message}");
}
处理 gzip/deflate 压缩响应
var httpClientHandler = new HttpClientHandler
{AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
};
var httpClient = new HttpClient(httpClientHandler);
取消操作
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10)); // 10秒超时
try {var response = await client.GetAsync("https://slow-api.com", cts.Token);
} catch (TaskCanceledException) {// 处理超时
}
http://www.xdnf.cn/news/14565.html

相关文章:

  • 【Dicom标准】dicom数据中pixelData显示处理流程详细介绍
  • Linux 服务器运维:磁盘管理与网络配置
  • 一个免费的视频、音频、文本、图片多媒体处理工具
  • ICM-20948 Wake on Motion功能开发全过程(8)
  • Python 的内置函数 hash
  • python模块常用语法sys、traceback、QApplication
  • 操作系统内核态和用户态--2-系统调用是什么?
  • 决策树:化繁为简的智能决策利器
  • GO语言---数组
  • 【Docker基础】Docker镜像管理:docker rmi、prune详解
  • 经典:在浏览器地址栏输入信息到最终看到网页的全过程,涉及网络协议以及前后端技术
  • Vue状态管理实践:使用Vuex进行前端状态管理
  • FVISION 未来视界工作室:AI驱动的创新与智能外包平台
  • TodoList 案例(Vue3): 使用Composition API
  • Snapchat矩阵运营新策略:亚矩阵云手机打造高效社交网络
  • 基于SpringBoot+Uniapp的活动中心预约小程序(协同过滤算法、腾讯地图、二维码识别)
  • 【论文笔记】【强化微调】TinyLLaVA-Video-R1:小参数模型也能视频推理
  • SQLite 数据库操作完整指南
  • Spring Boot邮件发送终极指南:从基础到高级应用
  • AI大模型学习之基础数学:高斯分布-AI大模型概率统计的基石
  • RocketMQ--为什么性能不如Kafka?
  • Mac电脑-Markdown编辑器-Typora
  • springboot垃圾分类网站
  • 浅议 3D 展示技术为线上车展新体验带来的助力​
  • Qt的学习(七)
  • Kubernetes多容器Pod实战
  • 操作系统进程与线程核心知识全览
  • 一个小BUG引发的对Mybatis-Plus的模糊查询的思考
  • C 语言结构体:从基础到内存对齐深度解析
  • word-spacing 属性