应复用httpclient实例,.net core 2.1+推荐全局复用或使用ihttpclientfactory管理,避免频繁创建导致socket耗尽和connection refused异常。

HttpClient 实例该不该复用?
.NET Core 2.1+ 推荐全局复用同一个 HttpClient 实例,而不是每次请求都 new 一个。频繁创建会耗尽 socket 连接池,出现 SocketException: Too many open files 或 HttpRequestException: Connection refused。
- 复用方式:注册为单例(
services.AddSingleton<httpclient>()</httpclient>)或用IHttpClientFactory(更推荐) - 不要写
using var client = new HttpClient()在方法内——这会导致连接未及时释放 - 如果必须自定义配置(如超时、Header),用
IHttpClientFactory.CreateClient("name")配合命名客户端
Get 请求传参:QueryString 还是 URI 拼接?
一律用 UriBuilder 或 FormUrlEncodedContent(不适用 Get)以外的正规方式构造 URL,别手动字符串拼接。
- 手动拼接
"@#@#@#@#@#@#@#@#@#@0=" + userId容易漏转义,遇到userId = "abc&name=xxx"就直接破坏 Query 结构 - 正确做法:
var uri = new UriBuilder("https://api.com/user") { Query = $"id={Uri.EscapeDataString(userId)}&name={Uri.EscapeDataString(name)}" }; - 或用第三方库如
Microsoft.AspNetCore.WebUtilities.QueryHelpers的AddQueryString
Post 发送 JSON:Content-Type 和序列化别搞混
HttpClient.PostAsync 不会自动设 Content-Type: application/json,也不处理对象序列化——这两步都得手动做。
- 错误写法:
client.PostAsync(url, new StringContent(JsonConvert.SerializeObject(obj), Encoding.UTF8))—— 缺少Content-Type头,服务端可能解析失败 - 正确写法:
var json = JsonSerializer.Serialize(obj); var content = new StringContent(json, Encoding.UTF8, "application/json"); await client.PostAsync(url, content);
- .NET 6+ 更简洁:
JsonSerializer.SerializeToUtf8Bytes(obj)配合new ByteArrayContent(...)可避免字符串编码开销
异步调用没 await 会怎样?
HttpClient 所有核心方法(GetAsync、PostAsync、ReadAsStringAsync)都是异步的,不加 await 会导致:
- 方法立即返回未完成的
Task,后续代码继续执行,结果变量为null或默认值 - 如果在 ASP.NET Core Controller 中返回未 await 的 Task,可能触发
InvalidOperationException: Headers are read-only(因响应已提交) - 极少数情况“看似正常”,实则后台线程仍在跑,资源泄漏且难以调试
务必检查所有调用链是否完整 await,尤其注意封装了请求的工具方法里有没有漏掉 await。
跨域、证书验证、重试策略这些属于进阶场景,先确保基础调用不出错——URL 拼对、头设对、JSON 序列化对、async/await 对,就已经避开了 80% 的线上故障。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










