I have a problem with the HttpClientFactory, i am trying to inject a CancellationTokenSource from DI to my "SomeClient" that configured to be like a:
services.AddHttpClient<ISomeClient, SomeClient>(a =>
a.BaseAddress = new Uri(address))
and i am injecting cancellationTokenSource in Startup.cs in the AddScoped<>().
If i add CancellationTokenSource to SomeClient constructor it will say
Cannot resolve scoped service 'System.Threading.CancellationTokenSource' from root provider.
but if i create something like:
services.AddScoped<ISomeClient, SomeClient>();
and make a new local HttpClient in the constructor, and inject CancellationTokenSource, everything will be fine.
So my question is how to use CancellationTokenSource with HttpClientFactory?
For AddHttpClient
, it will register SomeClient
as Transient
. But you register CancellationTokenSource
as Scoped
. This is the root caused.
HttpClientFactoryServiceCollectionExtensions.cs
public static IHttpClientBuilder AddHttpClient<TClient>(this IServiceCollection services)
where TClient : class
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
AddHttpClient(services);
var name = TypeNameHelper.GetTypeDisplayName(typeof(TClient), fullName: false);
var builder = new DefaultHttpClientBuilder(services, name);
builder.AddTypedClient<TClient>();
return builder;
}
HttpClientBuilderExtensions
public static IHttpClientBuilder AddTypedClient<TClient>(this IHttpClientBuilder builder)
where TClient : class
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Services.AddTransient<TClient>(s =>
{
var httpClientFactory = s.GetRequiredService<IHttpClientFactory>();
var httpClient = httpClientFactory.CreateClient(builder.Name);
var typedClientFactory = s.GetRequiredService<ITypedHttpClientFactory<TClient>>();
return typedClientFactory.CreateClient(httpClient);
});
return builder;
}
So, you could try register CancellationTokenSource
as Transient
.
services.AddTransient<CancellationTokenSource>();