.NET 6 中如何将已弃用的 WebClient 替换为 HttpClient?
方案合理性确认
你当前的实现完全符合.NET官方的WebClient替代最佳实践,核心逻辑100%对齐原有WebClient的功能,是合理的:
- 基于
IHttpClientFactory创建HttpClient,从根源避免了手动实例化HttpClient导致的套接字耗尽、DNS更新不生效的经典问题 - 请求头、Content-Type、编码设置的逻辑和原有WebClient完全一致,非2xx状态码抛出异常的行为也和
UploadString原生逻辑对齐 - 自定义请求头
user_key、Session_key添加在HttpRequestMessage上的写法更安全,不会出现多线程下请求头冲突的问题
可优化的细节
1. 补全返回值读取逻辑
你当前的实现缺少了原有代码中获取返回字符串的步骤,补全以下代码即可完全对齐原有逻辑:
string serverResponse = await response.Content.ReadAsStringAsync();
2. 复用JSON序列化配置
如果项目有统一的JSON序列化规则(比如驼峰命名、空值忽略、日期格式化等),可以提前定义静态的JsonSerializerOptions实例,避免每次序列化重复初始化配置,提升性能:
// 全局静态配置 private static readonly JsonSerializerOptions _jsonSerializeOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, IgnoreNullValues = true, // 其他自定义配置 }; // 序列化时传入配置 string json = JsonSerializer.Serialize(sms, _jsonSerializeOptions);
3. 提前配置HttpClient减少重复代码
如果该SMS接口是项目内高频调用的接口,可以在DI注册阶段就提前配置好基地址、通用请求头等,简化业务代码:
// Program.cs 中注册 builder.Services.AddHttpClient("SmsApiClient", client => { client.BaseAddress = new Uri(_baseUrl); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json)); }); // 业务代码中直接创建命名客户端即可 HttpClient httpClient = _httpClientFactory.CreateClient("SmsApiClient");
4. 用扩展方法简化代码(.NET 5+ 支持)
如果你的项目运行时是.NET 5及以上版本,可以使用内置JSON扩展方法省略手动序列化JSON、创建StringContent的步骤,代码更简洁:
HttpClient httpClient = _httpClientFactory.CreateClient(); var requestUrl = "sms"; // 配置BaseAddress后可直接使用相对路径 HttpRequestMessage request = new(HttpMethod.Post, requestUrl); request.Headers.Add("user_key", tokens[0]); request.Headers.Add("Session_key", tokens[1]); request.Content = JsonContent.Create(sms); // 内部自动处理序列化和ContentType设置 using HttpResponseMessage response = await httpClient.SendAsync(request); response.EnsureSuccessStatusCode(); string serverResponse = await response.Content.ReadAsStringAsync();
5. 同步场景的兼容处理
原有WebClient.UploadString是同步方法,你当前使用的异步方案是更推荐的做法,吞吐量更高。如果业务场景必须兼容同步调用,可以将异步调用改为:
using HttpResponseMessage response = httpClient.SendAsync(request).GetAwaiter().GetResult();
注意:非必要不推荐同步调用,可能导致线程池阻塞问题
内容的提问来源于stack exchange,提问作者Fabius
相关产品推荐
相关产品推荐

