I'll chime in though I expect at this point you've solved this. HttpClient has a couple of known problems when it comes to how to instantiate and use it, especially with Dependency Injection in .Net Core and .Net 5+. One of these has to do with Sockets. I'll let you google that, but in general, an HttpClient should be created once and reused.
The second problem has to do with DNS, but again, I'll defer that to google.
Basically, there are 2 patterns you want to follow in your Startup/Program (one or the other). AddHttpClient is the one I use. HttpClientFactory is the other.
Here is a .Net 6 Console application I wrote in Fiddler:
using System;
using System.Net.Http;
using System.Text;
using Microsoft.Extensions.DependencyInjection;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Microsoft.Extensions.Logging;
public class Program
{
public class Data
{
public string Name {get; set;}
public string Address {get; set;}
}
public class PostResponse
{
public string Id {get; set;}
public string Message {get; set;}
}
public interface IMyHttpClient
{
Task<PostResponse> PostAsync(Data data, CancellationToken cancellationToken);
}
public class MyHttpClient : IMyHttpClient
{
private readonly HttpClient _httpClient;
public MyHttpClient(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<PostResponse> PostAsync(Data data, CancellationToken cancellationToken)
{
HttpResponseMessage response = null;
// Newtonsoft here but feel free to use whatever serializer. I have generally moved to the System.Text.Json.
var requestBody = JsonConvert.SerializeObject(data);
HttpContent content = new StringContent(requestBody, Encoding.UTF8, "application/json");
var request = new HttpRequestMessage()
{
RequestUri = new System.Uri("https://my.url.com"),
Method = HttpMethod.Post,
Content = content
};
response = await _httpClient.SendAsync(request, cancellationToken);
//Check if they canceled before doing an expensive operation
cancellationToken.ThrowIfCancellationRequested();
if (!response.IsSuccessStatusCode)
{
// throw or log or whatever.
throw new Exception($"{response.StatusCode.ToString()}:{response.ReasonPhrase}");
}
var responseContent = response.Content != null? await response.Content.ReadAsStringAsync(): null;
var postResponse = JsonConvert.DeserializeObject<PostResponse>(responseContent);
return postResponse;
}
}
public static async Task Main()
{
var services = new ServiceCollection();
// configure logging
services.AddLogging(builder =>
{
builder.AddConsole();
});
// HERE IS YOUR PATTERN 1. Use AddHttpClient.
services.AddHttpClient<IMyHttpClient, MyHttpClient>();
var serviceProvider = services.BuildServiceProvider();
var logger = serviceProvider.GetService<ILoggerFactory>()
.CreateLogger<Program>();
logger.LogDebug("Starting application");
var data = new Data()
{
Name = "Shirley",
Address = "123 Main St, Anytown, Anystate, Anyzip"
};
var client = serviceProvider.GetService<IMyHttpClient>();
var cancellationToken = new CancellationToken();
try
{
var response = await client.PostAsync(data, cancellationToken);
Console.WriteLine($"{response.Id}:{response.Message}");
}
catch(Exception ex)
{
Console.WriteLine($"Exception: {ex.Message}");
}
logger.LogDebug("All done!");
}
}