Closed JakeYallop closed 3 weeks ago
Tagging subscribers to this area: @dotnet/ncl See info in area-owners.md if you want to be subscribed.
Tagging subscribers to this area: @dotnet/ncl See info in area-owners.md if you want to be subscribed.
I would argue that overriding is an expected behavior in DI paradigm. But this scenario definitely will benefit from explicit documentation.
What's unfortunate here is that the "default" HttpClient
(the one auto-added with string.Empty
name) -- is also registered as a transient service
https://github.com/dotnet/runtime/blob/9be628743487aac580a5e933f08d459dc50c80fb/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/HttpClientFactoryServiceCollectionExtensions.cs#L65-L69
So, instead of failing, your not-anymore-"typed client" MyService
ends up being created with this "default" HttpClient
injected (which might be especially confusing because ConfigureHttpClientDefaults
was applied to that client as well)
On a side note, I should warn you regarding the use of scopes with HttpClientFactory
, there's a known limitation that different application scopes can end up sharing a single handler instance, for more information see https://learn.microsoft.com/en-us/dotnet/core/extensions/httpclient-factory#message-handler-scopes-in-ihttpclientfactory and https://github.com/dotnet/runtime/issues/47091
I would argue that overriding is an expected behavior in DI paradigm.
I agree with this - to me though, the name of the API suggests that I am configuring the HTTP client that is going to be injected into that service, rather than registering the service as well.
In fairness, its a mistake you only make once, and I've used typed clients before and not ran into such issues.
When a service containing a prior configured HttpClient is explicitly registered, any configuration for the client that service uses is then lost.
Consider the following simplified scenario.
MyService
is a service containing a HttpClient. Based on the configuration, I would expect MyService to be scoped and have a HttpClient with a rate limit of 1 request per second and have additional user agent headers. However, the rate limit nor the additional default request headers are applied.In this simplified scenario, its obvious to see that the service has been registered twice. Removing the
AddScoped<MyService>
call means the service is registered as transient (fromAddHttpClient<MyService>
), and the http client configuration then applies as expected.The primary message handler configured using ConfigureHttpClientDefaults is configured correctly, regardless of if there are multiple registrations of
MyService
.I'm not sure if there's a fix here, but I wanted to raise an issue for this as its very easy to make a mistake and accidentally remove all the configuration for a http client.
Output with misconfiguration (the mock data handler has a
Task.Delay(100)
in it):Expected output:
Full runnable code listing
```xml