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
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 the HttpClient it creates.
This means that you're not managing the lifetime of the HttpClient. The ServiceProvider is doing that behind the scenes. (You're not responsible for creating the client factory either.)
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.
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.
Related
I'm using RestSharp to make API calls. What I have learnt for HttpClient is that it can lead to socket exhaustion when too many instances are created: https://learn.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests
The RestClient class also accepts an HttpClient parameter, so I guess it's using HttpClient internally.
I'm not sure how RestSharp handles HttpClient instances internally, but should I instantiate the RestClient with a HttpClient created by the IHttpClientFactory implementation?
new RestClient(httpClientFactory.CreateClient())
When you pass the HttpClient instance like that, it won't be disposed. The intention is that you might have a pre-configured HttpClient instance used as a singleton. It's not a good idea to dispose an external dependency by default, so RestSharp doesn't do it.
Besides, the issue with socket exhaustion is not caused by HttpClient being instantiated for each request but by the underlying HttpMessageHandler.
If you want to use the IHttpClientFactory internal instance caching (it doesn't cache the client, it caches the HttpMessageHandler instances), you can do it like this:
using var httpClient = httpClientFactory.CreateClient();
using var restClient = new RestClient(httpClient);
You can also tell RestSharp to dispose the HttpClient instance:
using var restClient = new RestClient(httpClientFactory.CreateClient(), true);
and the factory will take care of caching the message handler.
The next major version of RestSharp will hopefully make it a bit easier.
Based on this https://stackoverflow.com/a/65400954/11065063
and we also have this issue in our production system, we have an instance as singleton in our DI container, plus we also have old codes that creating new instance inside using statement, and we are encountering transient errors that the request has been cancelled and we don't have any idea how's that happening.
I've got a .Net Core project that needs to connect to around 4 different API services, I'm no expert with any of the HttpClient code, but from what I found, was that you'd generally only want to reuse one instance of your HttpClient. From what I can tell the general consensus is to use the HttpClientFactory in .Net Core by registering it in your Startup class and then requesting it using DI.
Now most of my default headers and such are all generally the same besides the BaseAddress url, how should I go about this when connecting to 4 diff API services? Should I register 4 different named clients or have one client with all the default information pre-set and then manually configure it as needed e.g. configuring the address?
General questions would be as I'm fairly new to this is, it's been said to re-use one instance of an HttpClient.
If I create 4 different named clients for each API service, wouldn't this create 4 instances of the HttpClient when I call the .CreateClient() method?
The .CreateClient() creates a new instance every time it's called, doesn't this defeat the purpose of having one instance of the HttpClient if say I need to make 3 different calls to one API service, each of those calls will call a .CreateClient() to establish some sort of connection and that will create 3 instances of the HttpClient?
Any help for clarity would be appreciated,
Thanks!
The purpose of using IHttpClientFactory is not to reuse instances of HttpClient. Instead, it is to reuse (by pooling) instances of HttpMessageHandler (actually HttpClientHandler, which is derived from the abstract HttpMessageHandler) that is the underlying object that manages HTTP connections & sockets. This diagram from Microsoft Docs shows it well.
You were worried that frequent calls to IHttpClientFactory.CreateClient() will create the same problem as frequent calls to new HttpClient(). However, this is not the case. As explained by Microsoft docs, the reason that frequent calls to new HttpClient() will result in socket exhaustion is that this constructor will create a new instance of HttpMessageHandler:
However, the issue isn't really with HttpClient per se, but with the default constructor for HttpClient, because it creates a new concrete instance of HttpMessageHandler, which is the one that has sockets exhaustion and DNS changes issues mentioned above.
You can see from the source code of IHttpClientFactory that it does not use the parameterless constructor of HttpClient in CreateClient(). Instead, it gets the HttpMessageHandler from a pool and inject it into the created HttpClient.
Whether you are using typed or named clients, you should use the HttpClient instance as if it's a transient object: it is cheap to create and you don't need to cache it for long periods of time.
Can anybody help me to understand following in context to Dependency Injection in Asp.Net 5 and object dispose.
I need to understand if my Service implements IDispose interface ,who will call dispose method.
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IService, Service>();
services.AddScoped<IService, Service>();
services.AddSingleton<IService, Service>();
services.AddInstance<IService, Service>();
}
IServiceCollection contains the set of services available in your application. You defines the services you want to use and their lifetime, and the application will instantiate and dispose them for you.
There are 4 different lifetimes :
Transient
Transient lifetime services are created each time they are requested. This lifetime works best for lightweight, stateless service.
Scoped
Scoped lifetime services are created once per request.
Singleton
Singleton lifetime services are created the first time they are requested, and then every subsequent request will use the same instance. If your application requires singleton behavior, allowing the services container to manage the service’s lifetime is recommended instead of implementing the singleton design pattern and managing your object’s lifetime in the class yourself.
Instance
You can choose to add an instance directly to the services container. If you do so, this instance will be used for all subsequent requests (this technique will create a Singleton-scoped instance). One key difference between Instance services and Singleton services is that the Instance service is created in ConfigureServices, while the Singleton service is lazy-loaded the first time it is requested.
The asp.net 5 official documentation is great, take time to read it : http://docs.asp.net/en/latest/fundamentals/dependency-injection.html
The documentation doesn't mention how exactly the dependencies lifetimes are handled by the dependency injection service but if you search in the code, you will find the ServiceProvider class, who manages the lifetimes : ServiceManager class
To be a little more specific, when a scope is created, the service scope factory returns a new service scope, who is instanciated with a service provider. When the dependency injection service have to dispose a service, he calls the service scope's dispose method, who calls the service provider's dispose method.
How the service provider works ? He has all the service scopes in a property, named _resolvedServices, and all the transiant disposables in a property named _transientDisposables. When the dispose() method of the service provider is called, he loops on all the items he has in this two properties, and for each object calls his dispose method.
You have all the source code here : Dependency Injection source code
Is there a possibility to register a service scoped to the Session?
In the documentation I found the possibility to add
Transient: New instance each time the service is requested
Scoped: New instance for each HTTP request
Singleton: One instance as long as the server is up and running
Instance: Basically a singleton but with the instance I create
But I did not find anything to register a service scoped to the Session.
Is there a workaround for this? Or is it just not possible?
It would be possible, of course. But as far as I know it would need some coding to write custom solution. I would start with try to write and integrate custom 'life time manager' (in unity nomenclature), or create custom factory for subject service and register it as singleton.