C#怎么发送HTTP请求 C#如何使用HttpClient调用REST API接口获取数据【网络】
C#怎么发送HTTP请求 C#如何使用HttpClient调用REST API接口获取数据【网络】 HttpClient 必须复用,不能每次 new 很多开发者踩的第一个坑,就是图省事,在方法里直接 new HttpClient()。这看似方便,实则后患无穷。频繁创建新实例,会导致底层套接字端口来不
C#怎么发送HTTP请求 C#如何使用HttpClient调用REST API接口获取数据【网络】

HttpClient 必须复用,不能每次 new
很多开发者踩的第一个坑,就是图省事,在方法里直接 new HttpClient()。这看似方便,实则后患无穷。频繁创建新实例,会导致底层套接字端口来不及释放,最终引发端口耗尽和恼人的 SocketException。不仅如此,每次新建连接,DNS解析缓存也无法复用,连接池的优势荡然无存,性能自然上不去。
那么,正确的复用姿势是什么?在 .NET Core 2.1 及更高版本中,最佳实践是通过依赖注入,使用 IServiceCollection.AddHttpClient() 将其注册为单例或作用域服务。如果是在控制台应用或简单的脚本里,一个简单有效的办法是将其声明为静态只读字段。
- 典型的错误写法:
var client = new HttpClient();放在方法内部 —— 这意味着每次调用都会新建一个。 - 推荐的静态复用写法:
private static readonly HttpClient _client = new HttpClient(); - 额外提醒:除非你非常确定该实例的生命周期已经结束且后续绝不会再使用,否则不要手动去调用
_client.Dispose(),让框架来管理它。
GET 请求带参数要用 Uri.EscapeDataString 或 QueryHelpers
构建GET请求的查询字符串,是另一个高频出错点。直接进行字符串拼接,比如手写 ?key=value&key2=value2,一旦参数值里包含空格、中文、&、=这些特殊字符,整个URL结构就可能被破坏,导致服务端返回400错误或者解析异常。尤其是当参数值来自用户输入或数据库时,风险极高。
所以,别再手动拼接了。推荐使用 UriBuilder 配合 QueryHelpers(需要引用 Microsoft.AspNetCore.WebUtilities 包)来安全地构建URL。
- 推荐方式示例:
var uri = new UriBuilder("https://api.example.com/users"); uri.Query = QueryHelpers.AddQueryString("", new Dictionary{ ["name"] = "张三", ["page"] = "1" }); var response = await _client.GetAsync(uri.ToString()); - 不推荐的做法:使用类似
$"https://...?name={name}"的字符串插值。这种方式下,中文字符会变成乱码,而参数中的&符号更可能直接截断查询字符串,引发不可预知的问题。
POST JSON 数据必须设 Content-Type 并用 StringContent
发送POST请求提交JSON数据时,一个常见的疏忽是忘了设置正确的请求头。很多初学者会这样写:client.PostAsync(url, new StringContent(json, Encoding.UTF8)),结果服务端收到的虽然是一段JSON文本,但因为缺少 Content-Type: application/json 这个关键头信息,无法正确解析请求体,最终返回415 Unsupported Media Type错误。
- 正确的完整写法应该是:
var json = JsonSerializer.Serialize(new { username = "alice", pwd = "123" }); var content = new StringContent(json, Encoding.UTF8, "application/json"); var response = await _client.PostAsync("https://api.example.com/login", content); - 需要警惕的混淆:不要用
FormUrlEncodedContent来发送JSON。这个类是为application/x-www-form-urlencoded格式设计的,它会将整个JSON字符串当作一个字段值进行编码,导致服务端完全无法解析出预期的对象结构。 - 补充一点:如果调用的API要求Bearer Token认证,记得在发送请求前设置好请求头:
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
异步方法必须 await,别用 .Result 或 .Wait()
在异步编程模型里,阻塞异步任务是一个大忌。特别是在ASP.NET Core这类拥有同步上下文(SynchronizationContext)的Web应用环境中,在控制器里调用 task.Result 或 .Wait() 极易引发线程死锁,导致应用无响应。HttpClient 的所有核心方法,如 GetAsync、PostAsync,都是真正的异步操作,必须用 await 关键字来驱动。
- 绝对要避免的写法:
var res = client.GetAsync(url).Result;或者.Wait()。 - 在ASP.NET Core控制器中的正确做法:将Action方法标记为
async Task,并在方法体内使用await。 - 在控制台程序中的处理:对于C# 7.1及以上版本,可以使用
static async Task Main(string[] args)作为入口点。如果需要在其他地方同步等待,可以考虑使用await MainAsync().ConfigureAwait(false)来避免潜在的上下文问题。
说到底,使用HttpClient发送HTTP请求,真正的难点往往不在于“如何发送出去”,而在于背后的连接复用策略、参数编码的安全性以及异步流程的控制。这三个关键点如果没对齐,接口在测试时可能一切正常,一旦上线,间歇性的失败、缓慢的响应,甚至持续上涨的内存消耗,就会接踵而至。这才是问题的关键所在。
Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。
极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。
















