I've stumbled in a peculiar case where the named HttpClient
that I want to build is run with an async function, like this:
services.AddHttpClient("customClient", async (serviceProvider, httpClient) => {...});
And then when I try to recall it from an instance of IHttpClientFactory
inside a service in which I want to use it, like this:
//Constructor start
this.httpClient = httpClientFactory.CreateClient("customClient");
//Constructor end
I end up with a half-assed HttpClient
, where the BaseAddress
is set but the DefaultRequestHeaders.Authorization
is missing despite both are set in same AddHttpClient
async function(but the Authorization
header is only set after awaiting 1 call).
So I was wondering, like in the question title: what happen when CreateClient(name)
is called synchronously meanwhile the HttpClient
setup is asynchronous?
Isn't there a mechanism that awaits this kind of definitions? From what I tried, it doesn't seem so.
CodePudding user response:
So I was wondering, like in the question title: what happen when CreateClient(name) is called synchronously meanwhile the HttpClient setup is asynchronous?
The setup isn't allowed to be asynchronous. If you look at all the overloads, none of them take an asynchronous delegate.
And if you think about it, that makes sense. Dependency injection in general has rejected asynchronous initialization because if they allowed it, then every dependency resolution would have to be await
ed.
Isn't there a mechanism that awaits this kind of definitions? From what I tried, it doesn't seem so.
Nope. The common patterns are:
- If this is a one-time initialization, then do it before setting up your DI, and use the resulting value in your DI setup.
- If this must be done after startup, then consider injecting an asynchronous HttpClient factory (no type like this is built-in; you'll have to use your own).
- If this needs to be done periodically (e.g., refreshing access tokens), then what you really want is a middleware (delegating handler) that (re-)acquires the token on demand.