c# 如何进行http请求

应全局复用单个 HttpClient 实例以避免内存泄漏和 socket 耗尽;GET 请求用 EnsureSuccessStatusCode() 自动校验状态码;POST JSON 时用 StringContent 设置 application/json 且省略 charset;超时用 CancellationToken 控制;绕过 SSL 验证仅限测试且需注意 handler 生命周期管理。

HttpClient 发起最简 GET 请求

绝大多数场景下,直接用 HttpClient 就够了,它线程安全、支持连接池、能复用底层 TCP 连接。别每次请求都 new 一个实例——这是最常见的内存泄漏和 socket 耗尽源头。

正确做法是全局复用单个 HttpClient 实例(比如声明为 static readonly 或注入到 DI 容器):

private static readonly HttpClient _client = new HttpClient();

public async Task GetContentAsync(string url)
{
    var response = await _client.GetAsync(url);
    response.EnsureSuccessStatusCode();
    return a

wait response.Content.ReadAsStringAsync(); }

注意:EnsureSuccessStatusCode() 会在 HTTP 状态码非 2xx 时抛出 HttpRequestException,避免手动检查 response.IsSuccessStatusCode

POST JSON 数据并读取响应

发 JSON 是高频需求,关键在设置正确的 Content-Type 和序列化方式。.NET 6+ 推荐用 System.Text.Json,轻量且无额外依赖。

  • HttpClient 默认不带 JSON 支持,需手动序列化 + 设置 StringContent
  • 别用 application/json; charset=utf-8 —— charset 在 JSON 媒体类型中是冗余且可能被某些服务拒绝的
  • 响应体同样建议用 ReadAsStringAsync()ReadAsByteArrayAsync(),避免阻塞线程
var data = new { Name = "Alice", Age = 30 };
var json = JsonSerializer.Serialize(data);
var content = new StringContent(json, Encoding.UTF8, "application/json");

var response = await _client.PostAsync("https://api.example.com/users", content);
var result = await response.Content.ReadAsStringAsync();

处理超时、重试和取消

生产环境必须控制请求生命周期。HttpClientTimeout 属性只作用于单次请求(包括 DNS 解析、连接、发送、接收),不适用于整个异步操作链;更灵活的方式是传入 CancellationToken

  • TimeSpan.FromSeconds(10) 创建 token: var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
  • cts.Token 传给所有 GetAsync/PostAsync 调用
  • 如需自动重试,不要手写 while 循环——引入 Polly 库更可靠,尤其配合指数退避
  • 注意:CancellationToken 取消后,HttpClient 不会主动中断底层 socket,但会尽快退出等待并抛出 OperationCanceledException

绕过 SSL 证书验证(仅限测试)

开发时遇到自签名证书报错 AuthenticationException: The remote certificate is invalid,临时方案是配置 HttpClientHandlerServerCertificateCustomValidationCallback

var handler = new HttpClientHandler
{
    ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true
};
var client = new HttpClient(handler);

这个回调返回 true 表示信任所有证书——上线前必须删掉,且不能用于任何生产或用户数据场景。真实项目应通过添加根证书或使用正式签发的域名证书解决。

真正容易被忽略的是:一旦用了自定义 HttpClientHandler,你就得自己管理它的生命周期;如果 handler 含有 unmanaged 资源(比如自定义 DNS 解析逻辑),没正确 dispose 会导致句柄泄露。