1

We are currently using the HttpClient to invoke the Web APIs from the MVC application.

The HttpClient is part of a static helper class as shown below

public static class ApiClient
{
    private static HttpClient MyHttpClient()
    {         
        HttpClient client = new HttpClient();               
        ...         
        return client;
    }

    public static T HttpGet<T>(string requestUri)
    {
        using (var client = MyHttpClient())
        {
            ...
        }
    }
}

and it is invoked from the MVC controller as given below

ApiClient.HttpGet<MyModel>("<<API URL>>");

So whenever the ApiClient is invoked, a new underlying connection will be opened which isn't the right way.

I read about HttpClientFactory and read this post and I resulted in modifying the creation logic as

private static HttpClient MyHttpClient()
{
    var serviceProvider = new ServiceCollection().AddHttpClient().BuildServiceProvider();
    var httpClientFactory = serviceProvider.GetService<IHttpClientFactory>();
    var client = httpClientFactory.CreateClient();
    //HttpClient client = new HttpClient();
    ...
    return client;
}

Will this prevent from opening multiple connections even if invoked multiple times?

Camilo Terevinto
  • 31,141
  • 6
  • 88
  • 120
Gopi
  • 5,656
  • 22
  • 80
  • 146
  • @PavelAnikhouski Yes! for the same reason I wanted to use HttpClientFactory as described in later section of the question. – Gopi Apr 01 '19 at 11:59
  • 2
    By the way, your "creation logic" is completely wrong. You should *never* create a new `ServiceCollection`. You should inject `IHttpClientFactory` wherever you need a `HttpClient` – Camilo Terevinto Apr 01 '19 at 12:06
  • 1
    @CamiloTerevinto Agreed. Since 'ApiClient' class is declared static, I will be able to inject 'IHttpClientFactory ' and that is where I am not able to proceed further. Will be helpful if you can provide some insights. – Gopi Apr 01 '19 at 12:11
  • Cannot you use a singleton instead? – Camilo Terevinto Apr 01 '19 at 12:11
  • @CamiloTerevinto Yes, singleton could help but IHttpClientFactory seems to be available to address this exact scenario and hence I would like to use it. I don't mind changing the way the ApiClient is invoked while calling the API from MVC. – Gopi Apr 01 '19 at 12:15
  • Can you share from where did you get the idea that an interface that has to be injected is meant to solve a problem with static classes? That scenario cannot be found in the documentation: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-2.2 – Camilo Terevinto Apr 01 '19 at 12:29
  • Why the downvotes? – Gopi Apr 01 '19 at 13:21

1 Answers1

4

The IHttpClientFactory functionality is predicated on dependency injection, and statics are fundamentally incompatible with dependency injection. As the docs clearly show, the correct way to do this is:

public class ApiClient
{
    private readonly HttpClient _client;

    public ApiClient(HttpClient client)
    {
        _client = client;
    }

    ...
}

And then you register this service in ConfigureServices:

services.AddHttpClient<ApiClient>(c => { ... });

The client class should not be static and there's no reason for it to be static.

Chris Pratt
  • 232,153
  • 36
  • 385
  • 444