如何在 .NET 6 中用 HttpClient 替换过时的 WebClient

Posted

技术标签:

【中文标题】如何在 .NET 6 中用 HttpClient 替换过时的 WebClient【英文标题】:How to replace obsolete WebClient with HttpClient in .NET 6 【发布时间】:2021-12-01 13:27:05 【问题描述】:

由于 WebClient 在 .NET 6 中已弃用,我想使用 WebClient 将以下代码转换为使用 HttpClient 调用 REST Web API 的等效代码:

using WebClient client = new();
client.Encoding = Encoding.UTF8;
client.Headers.Set(HttpRequestHeader.ContentType, "application/json");
client.Headers.Add("user_key", tokens[0]);
client.Headers.Add("Session_key", tokens[1]);
string json = JsonSerializer.Serialize(sms);
string serverResponse = client.UploadString(_baseUrl + "sms", "POST", json);

目前,我实现了以下解决方案:

HttpClient httpClient = _httpClientFactory.CreateClient();
HttpRequestMessage request = new(HttpMethod.Post, _baseUrl + "sms");
request.Headers.Add("user_key", tokens[0]);
request.Headers.Add("Session_key", tokens[1]);
string json = JsonSerializer.Serialize(sms);
request.Content = new StringContent(json, Encoding.UTF8, MediaTypeNames.Application.Json);
using HttpResponseMessage response = await httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();

我认为上述解决方案是替换原始代码的最干净,最有效的方法。专家可以确认一下吗?

【问题讨论】:

【参考方案1】:

看起来很简单:

HttpClient client = new()

    BaseAddress = new Uri(_baseUrl)
;

using HttpRequestMessage request = new(HttpMethod.Post, "sms");
request.Headers.Add("user_key", tokens[0]);
request.Headers.Add("Session_key", tokens[1]);

string json = JsonSerializer.Serialize(sms);
request.Content = new StringContent(json, Encoding.UTF8)

    Headers =
    
        ContentType = new("application/json")
    
;

using HttpResponseMessage response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
string serverResponse = await response.Content.ReadAsStringAsync();

但是,您可能希望use the IHttpClientFactory to create your HttpClient instances,因为这提供了几个好处 - 特别是池化底层消息处理程序,以避免性能问题。

您可能还想考虑使用the PostAsJsonAsync extension method,这可以简化此代码。

【讨论】:

但是与 WebClient 相比,没有简单的方法可以跟踪下载/上传进度,对吧?你需要做一些流 writeasync/readasync 逻辑。 @AyCe 看起来还不错:Progress bar with HttpClient 是的,我就是这个意思,我也看到了。问题是针对 Windows 运行时的,我还没有检查与 .NET Framework/Core/5.0/6.0 的兼容性如何。【参考方案2】:

.Net 6 支持同步 Send()

这是一个简单的 GET:

using var httpClient = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://api.example.com/api/v1/get");
var response = httpClient.Send(request);
using var reader = new StreamReader(response.Content.ReadAsStream());
var responseBody = reader.ReadToEnd();

这是一个帖子:

var handler = new HttpClientHandler 
    AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
;

var client = new HttpClient(handler) 
    BaseAddress = new Uri(_baseurl) 
;

var webRequest = new HttpRequestMessage(HttpMethod.Post, "sms") 
    Content = new StringContent(json, Encoding.UTF8, "application/json")
;

webRequest.Headers.Add("user_key", tokens[0]);
webRequest.Headers.Add("Session_key", tokens[1]);

var response = client.Send(webRequest);
var reader = new StreamReader(response.Content.ReadAsStream());
var responseBody = reader.ReadToEnd();

【讨论】:

您的回答没有提供任何有价值的细节,说明为什么它比 OP 当前使用的解决方案更好。 这不是“更好” - 但它是人们可能想知道的新功能。

以上是关于如何在 .NET 6 中用 HttpClient 替换过时的 WebClient的主要内容,如果未能解决你的问题,请参考以下文章

《ASP.NET Core 6框架揭秘》实例演示[17]:利用IHttpClientFactory工厂来创建HttpClient

C#中HttpClient使用注意:预热与长连接

C#中HttpClient使用注意:预热与长连接

如何在 .net 和 .net 核心中使用 HttpClient 调用多个客户端 API

如何在 .NET 测试中传入模拟的 HttpClient?

使用 System.Net.HttpClient 进行上传时如何跟踪进度? [复制]