.NET HttpClient – the correct way to use it

For ages I’ve been using the HttpClient in .NET without any issues, but usually I have a single endpoint and a singleton (or equivalent) of a class that uses the HttpClient. A while back I needed to call multiple different endpoints using the HttpClient and so I happily wrapped an instantiation of an HttpClient in a using statement, I mean after all it has an IDisposable interface so that makes sense right?

Well NO this is not the case. So don’t do this!

// Don't do this
using(var httpClient = new HttpClient())
{
   // do something with httpClient
}

This post stems from a work colleague pointing me to the post YOU’RE USING HTTPCLIENT WRONG AND IT IS DESTABILIZING YOUR SOFTWARE.

What does the documentation say?

If you take a look at the HttpClient Class documentation states

HttpClient is intended to be instantiated once and re-used throughout the life of an application. Instantiating an HttpClient class for every request will exhaust the number of sockets available under heavy loads. This will result in SocketException errors.

If we take a look at some C# templates in Visual Studio, for example the ASP.NET core Blazor application template, it will give you a scoped instance of the HttpClient, for example

builder.Services.AddScoped(sp => 
  new HttpClient 
    { 
       BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) 
    }
);

So how are we supposed to use a single instance of HttpClient

Let’s now assume that we create an HttpClient per application. Then how do we call multiple service endpoints without having changes affect different endpoint calls and is it threadsafe?

Is the HttpClient thread-safe? Well the answer is both yes and no.

Changing properties on the HttpClient are not threadsafe or at least cannot/should not be modified whilst there are outstanding requests. However methods such as GetAsync, PostAsync, SendAsync etc. are threadsafe which then leads us to how to se set-up different calls, i.e. maybe different headers etc. on all our calls. The answer here is to use SendAsync and create an HttpRequestMessage. This allows us to specify many of the properties we’ll need per HTTP call.

References

YOU’RE USING HTTPCLIENT WRONG AND IT IS DESTABILIZING YOUR SOFTWARE
HTTPCLIENT CREATION AND DISPOSAL INTERNALS: SHOULD I DISPOSE OF HTTPCLIENT?