Reusing HttpClient with Dependency Injection
Full source code available here.
If you are using HttpClient
to make requests for you, you might have come across some articles discussing how to reuse HttpClient
. They strongly advocate for using a single HttpClient
for as many requests as possible, i.e. not creating a new HttpClient
for every request.
Not having to create/dispose of the HttpClient
for every request should improve the performance of you application. One estimate states that every time you instantiate a HttpClient
takes 35ms.
In this article I will show you how to use dependency injection to reuse the HttpClient
in .Net Core, but the same principle applies in Framework 4.x applications.
The one advantage of creating a new HttpClient for every request is that you don’t need to worry about the DNS record of an endpoint changing during the lifetime of the application, this is common if you are swapping staging and production instances during a deployment. But this is easyly(ish) handled by the ServicePointManger
.
Adding HttpClient to the DI Container
In Startup.cs
add the below lines.
1public void ConfigureServices(IServiceCollection services)
2{
3 Uri endPointA = new Uri("http://localhost:58919/"); // this is the endpoint HttpClient will hit
4 HttpClient httpClient = new HttpClient()
5 {
6 BaseAddress = endPointA,
7 };
8
9 ServicePointManager.FindServicePoint(endPointA).ConnectionLeaseTimeout = 60000; // sixty seconds
10
11 services.AddSingleton<HttpClient>(httpClient); // note the singleton
12 services.AddMvc();
13}
This approach is ideal if you have a limited number of endpoints and you know them at application startup. If you don’t know then endpoints at startup you can add the call to ServicePointManager
where you HttpClient
requests occur.
Using the HttpClient
Now I have the HttpClient registered with the Dependency Injection container, let’s take a look at the controller that uses it to make a request. See the inline comments.
1public class ValuesController : Controller
2{
3 private readonly HttpClient _httpClient; // declare a HttpClient
4
5 public ValuesController(HttpClient httpClient) // this is the singelton instance of HttpClient
6 {
7 _httpClient = httpClient; // assign it to the local HttpClient
8 }
9
10 // GET api/values
11 [HttpGet]
12 public async Task<IActionResult> Get()
13 {
14 string requestEndpoint = "api/products";
15
16 HttpResponseMessage httpResponse = await _httpClient.GetAsync(requestEndpoint); // make request
17 List<Product> products = await httpResponse.Content.ReasAsJsonAsync<List<Product>>();
18 return Ok(products);
19 }
20}
Full source code available here.