Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When using services.AddHttpClient, where is the HttpClient created?

I am trying to understand how HttpClient has been implemented for Captcha in Nop Commerce and for the sake of testability how creating new instance of HttpClient has been manage in Nop Commerce project.

I came across ValidateCaptchaAttribute and ValidateCaptchaFilter and I see HttpClient has been wrapped inside CaptchaHttpClient class but I don't understand from where does CaptchaHttpClient receive dependency for HttpClient and from where constructor of CaptchaHttpClient class is being called.

Inside ServiceCollectionExtensions class I see below code:

public static void AddNopHttpClients(this IServiceCollection services)
 {
    //default client
    services.AddHttpClient(NopHttpDefaults.DefaultHttpClient).WithProxy();

    //client to request current store
    services.AddHttpClient<StoreHttpClient>();

    //client to request nopCommerce official site
    services.AddHttpClient<NopHttpClient>().WithProxy();

    //client to request reCAPTCHA service
    services.AddHttpClient<CaptchaHttpClient>().WithProxy();
 }

But I don't see where HttpClient object is created:

var client = new HttpClient() // Where this is done?

Am I perhaps missing something?

Nop Commerce Version = 4.20

like image 202
Learning-Overthinker-Confused Avatar asked May 31 '19 07:05

Learning-Overthinker-Confused


People also ask

What is the use of HttpClient in C#?

The HttpClient class instance acts as a session to send HTTP requests. An HttpClient instance is a collection of settings applied to all requests executed by that instance. In addition, every HttpClient instance uses its own connection pool, isolating its requests from requests executed by other HttpClient instances.

What is AddHttpClient?

AddHttpClient(IServiceCollection) Adds the IHttpClientFactory and related services to the IServiceCollection. AddHttpClient(IServiceCollection, String) Adds the IHttpClientFactory and related services to the IServiceCollection and configures a named HttpClient.

What is HttpClient factory?

IHttpClientFactory is a contract implemented by DefaultHttpClientFactory , an opinionated factory, available since . NET Core 2.1, for creating HttpClient instances to be used in your applications.


2 Answers

From the documentation:

Adds the IHttpClientFactory and related services to the IServiceCollection and configures a binding between the TClient type and a named HttpClient. The client name will be set to the type name of TClient.

Roughly translated, services.AddHttpClient<CaptchaHttpClient>() means that CaptchaHttpClient has a dependency on HttpClient. This says that when injecting HttpClient into CaptchaHttpClient, don't just create a new one - use an implementation of IHttpClientFactory to provide one and inject that.

This means that you're not managing the lifetime of the HttpClient. The ServiceProvider is doing that behind the scenes.

This documentation explains why this exists and how it works.

A Typed Client is, effectively, a transient object, meaning that a new instance is created each time one is needed and it will receive a new HttpClient instance each time it's constructed. However, the HttpMessageHandler objects in the pool are the objects that are reused by multiple Http requests.

This means:

  • The thing you're registering - in this case CaptchaHttpClient is transient so that each time it's resolved, a new instance is created.
  • Each time it is created, a new HttpClient is created and injected.
  • Although the HttpClient is new, the HttpMessageHandler it depends upon is reused.

This uses a pool of HttpMessageHandler instances that we don't have to manage. Our class just depends on HttpClient without having to worry about the negative side effects that happen when we create/dispose an HttpClient each time we need one.

like image 169
Scott Hannen Avatar answered Oct 19 '22 18:10

Scott Hannen


I found this article helpful in furthering my understanding of IHttpClientFactory patterns.

When defining typed clients in your ConfigureServices method, the typed service is registered with transient scope. This means that a new instance is created by the DI container every time one is needed. The reason this occurs is that a [sic] HttpClient instance is injected into the typed client instance. That HttpClient instance is intended to be short lived so that the HttpClientFactory can ensure that the underlying handlers (and connections) are released and recycled.

like image 33
golfalot Avatar answered Oct 19 '22 18:10

golfalot