12

Since WebClient is deprecated in .NET 6, I want to convert the following code using WebClient with an equivalent code using HttpClient for calling a 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);

For now, I implemented the following solution:

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();

I think that the above solution is the cleanest and most efficient way to replace the original code. Can an EXPERT confirm this?

Fabius
  • 147
  • 1
  • 1
  • 4

2 Answers2

14

.Net 6 supports synchronous Send()

Here's a simple 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();

Here's a POST:

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();
Chris Harrington
  • 1,238
  • 2
  • 15
  • 28
3

Seems simple enough:

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();

However, you'll probably want to use the IHttpClientFactory to create your HttpClient instances, since that provides several benefits - particularly pooling the underlying message handler, to avoid performance problems.

You might also want to consider using the PostAsJsonAsync extension method, which could simplify this code.

Richard Deeming
  • 29,830
  • 10
  • 79
  • 151
  • 1
    But there is no easy way to track download/upload progress compared to WebClient, right? You would need to do some stream writeasync/readasync logic. – AyCe Feb 16 '22 at 08:23
  • @AyCe It doesn't look too bad: [Progress bar with HttpClient](https://stackoverflow.com/a/69826649/124386) – Richard Deeming Feb 16 '22 at 10:02
  • Yes, that's what I mean, I saw that too. The question was for Windows Runtime, I haven't checked how compatible to .NET Framework/Core/5.0/6.0 this is yet. – AyCe Feb 16 '22 at 10:07