3

I’m creating an API that serves as the bridge between the app and 2 other APIs. I want to know if what is the best way to do this. I’m using HttpClient. The app has almost a thousand users.

I read this article https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/. Should I really not use the using statement? Also I am doing synchronous api calls. Does this have any effect? Is what I did efficient?

Here is my code:

[HttpGet]
[Route("api/apiname")]     
public String GetNumberofP([FromUri]GetNumberofPRequest getNPRequest){          

    var request = JsonConvert.SerializeObject(getNPRequest);
    string errorMessage = "";           

    try{              
         httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.gettoken());

         var response = httpClient.GetAsync("api/MobileApp/GetNumberP?"
                      + "strCardNumber=" + getNPRequest.strCardNumber
                     + "&strDateOfBirth=" + getNPRequest.strDateOfBirth).Result;
         return response;
    }            
    catch (Exception e){                
        throw utils.ReturnException("GetNumberofP", e, errorMessage);           
    }      
}
Nic
  • 12,220
  • 20
  • 77
  • 105
Kate Lastimosa
  • 169
  • 2
  • 15
  • Why are you using blocking synchronous calls, when you an use async with change of 2 lines of code? `public async Task GetNumberofP([FromUri]GetNumberofPRequest getNPRequest)` and `var response = await httpClient.GetAsync(...);` – Tseng Mar 28 '19 at 09:42
  • Related: https://stackoverflow.com/questions/12553277/allowing-untrusted-ssl-certificates-with-httpclient/54707165 – Peter O. Mar 28 '19 at 14:55
  • 1
    Possible duplicate of [Do HttpClient and HttpClientHandler have to be disposed?](https://stackoverflow.com/questions/15705092/do-httpclient-and-httpclienthandler-have-to-be-disposed) – mjwills Mar 28 '19 at 22:44
  • Did my answer help you Kate? – Nic Mar 30 '19 at 02:42

2 Answers2

7

HttpClient does not need to be disposed and you should hold on to it to reuse it later.

One thing you can use (from the thread you linked):

You just provide your HttpClient factory and dispose methods and the LimitedPool does the rest:

_httpClientPool = new LimitedPool<httpclient>(
CreateHttpClient, client => client.Dispose(), HttpClientLifetime);

using (var httpClientContainer = _httpClientPool.Get())
{ ... use httpClientContainer.Value ... }

When httpClientContainer is disposed, the HttpClient is actually returned back to the pool for other threads to use. When lifetime is reached next dispose will eventually call the Dispose method.

See code here

Alternative for .Net Core

Implement it as described in this document.

The IHttpClientFactory can be registered by calling the AddHttpClient extension method on the IServiceCollection, inside the Startup.ConfigureServices method.

services.AddHttpClient();

Once registered, code can accept an IHttpClientFactory anywhere services can be injected with dependency injection (DI). The IHttpClientFactory can be used to create a HttpClient instance:

public MyConstructor(IHttpClientFactory clientFactory)
{
    _clientFactory = clientFactory;
}

public async Task OnGet()
{
    ....
    var client = _clientFactory.CreateClient();

    var response = await client.SendAsync(request);
    ...
}

No need to use using().

Nic
  • 12,220
  • 20
  • 77
  • 105
  • 4
    __Alternative for .Net Core only__ This statement is definitely wrong. You should have read the linked documentation, which states: _Projects targeting .NET Framework require installation of the Microsoft.Extensions.Http NuGet package. Projects that target .NET Core and reference the Microsoft.AspNetCore.App metapackage already include the Microsoft.Extensions.Http package_ – Tseng Mar 28 '19 at 08:06
2

If you are using asp.net core the right way to use HttpClient is explained in this article from Microsoft:

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-2.2#typed-clients

I usually use the typed client approach explained in the article.

This basically means that I delegate to the asp.net core container the injection of the http client in my class (a controller class, a service, a filter, whatever)

Doing so you can safely modify the http client in your class by adding all the request headers you need (you usually do it inside the constructor of your class).

You do not have to call dispose on the injected http client, you simply use it.

The asp.net core container will manage the http client lifetime for you and the pool of resources used by http client instances so that your app do not leak resources. All of this happens automatically.

Do not use sync calls. Make your action method async, and await on async methods of http client. Asp.net core fully support async code and make blocking requests does not make sense, doing so you will limit the scalability of your app.

Enrico Massone
  • 6,464
  • 1
  • 28
  • 56
  • The asp.net core http client support has been designed in order to avoid all the issues illustrated in the article you have linked in your question. – Enrico Massone Mar 28 '19 at 06:34
  • https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-2.2#typed-clients – Enrico Massone Mar 28 '19 at 06:39