In ASP.NET Core 2.1 app I am making REST request using HttpClient. I am using DelegatingHandlers to define some common behavior. The registration i here:
private static void AddRestServiceDataClient<TTypedHttpClient, TTypedHttpClientImpl>(this IServiceCollection services)
where TTypedHttpClient : class
where TTypedHttpClientImpl : RestServiceDataClient, TTypedHttpClient
{
var httpClientBuilder = services
.AddHttpClient<TTypedHttpClient, TTypedHttpClientImpl>()
.AddHttpMessageHandler<CachingHttpDelegatingHandler>()
.AddHttpMessageHandler<ExceptionHttpDelegatingHandler>()
.AddHttpMessageHandler<LoggingHttpDelegatingHandler>();
}
...
// EDIT: You should always register DelegatingHandlers as TRANSIENT (read answer for more).
services.AddScoped<ExceptionHttpDelegatingHandler>();
services.AddScoped<CachingHttpDelegatingHandler>();
services.AddScoped<LoggingHttpDelegatingHandler>();
I register DelegatingHandlers as Scoped, but in two different scopes (requests) I get the same DelegatingHandler. I mean that the constructor of DelegationgHandler is being called only once and the same instance is used across more requests (like singleton). Everything else is as expected - life cycle of other services, TypedHttpClients and HttpClient is ok.
I tested everything by breakpoint in constructor and I have testing Guid in every instance so I can distinguish instances.
When I register DelegatingHandlers as Transient it makes no difference.
TL;DR DelegatingHandlers are resolved like singleton even though they are registered as scoped. And this causes me mishmash in service lifestyles.