Correct way to use HttpClient in .NET 8?

836 Views Asked by At

I have a .NET 8 app where my app is constantly using HttpClient to send requests to a server. Every time that I think I have a handle on the "correct" way to use HttpClient, I start second guessing myself.

First, let's assume that this is a long running app that runs for days at a time collecting data and every few seconds, sends the readings to a server.

Let's also assume that I care about port exhaustion and any DNS issues that may arise.

So, I have created a class called (for this example) MyHttpClient. The reason I am doing this is to be able to pass in typed parameters and auto deserialize the response into that type. Anyway, that isn't important. But the MyHttpClient holds the HttpClient object in this example as you can see below.

I add the http client to the IServiceCollection.

In my example below, do I need to set the handler lifetime?

Does this example take care of port exhaustion and DNS related issues? Or, did I completely miss the point here?

Any feedback here would be greatly appreciated....

App.xaml.cs:

private void ConfigureServices(IServiceCollection services)
{
    services.AddHttpClient<MyHttpClient>("MyHttpClient", x =>
    {
        x.Timeout = TimeSpan.FromSeconds(5);
    })
    .ConfigurePrimaryHttpMessageHandler(() =>
    {
        // allow to connect to self-signed certificate ssl
        var handler = new HttpClientHandler();
        handler.ClientCertificateOptions = ClientCertificateOption.Manual;
        handler.ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) => true;
        return handler;
    });
}

MyHttpClient:

public class MyHttpClient
{
    private HttpClient _httpClient;

    public MyHttpClient(HttpClient client)
    {
        _httpClient = client;
    }

    public async Task<string> GetStringAsync(string url, TimeSpan timeout)
    {
        try
        {
            _httpClient.Timeout = timeout;

            CancellationToken cancellationToken = default;
            using (var response = await _httpClient.GetAsync(url, cancellationToken))
            {
                response.EnsureSuccessStatusCode();
                return await response.Content.ReadAsStringAsync();
            }
        }
        catch
        {
            return null;
        }
    }
}

Usage in SomeService:

public class SomeService
{
    private readonly MyHttpClient httpClient;

    public SomeService(MyHttpClient httpClient)
    {
        this.httpClient = httpClient;
    }

    public async Task<string> TestMe()
    {
        return await httpClient.GetStringAsync("https://example.com/api/boblawlaw", TimeSpan.FromSeconds(4));
    }
}
0

There are 0 best solutions below