HCR085¶
Multiple typed clients on one interface should use explicit names.
Why¶
AddHttpClient<TService, TImplementation>() creates a named client behind the scenes. Without an explicit name, that name is derived from TService.
Registering different implementations against the same service interface therefore makes both typed clients share one named-client configuration. Configuration callbacks are combined, so a client can silently receive another implementation's BaseAddress, headers, handlers, or resilience configuration.
Bad¶
services.AddHttpClient<IPaymentsClient, StripePaymentsClient>(
client => client.BaseAddress = new Uri("https://stripe.example"));
services.AddHttpClient<IPaymentsClient, AdyenPaymentsClient>(
client => client.BaseAddress = new Uri("https://adyen.example"));
Both registrations implicitly use the client name derived from IPaymentsClient.
Better¶
services.AddHttpClient<IPaymentsClient, StripePaymentsClient>(
nameof(StripePaymentsClient),
client => client.BaseAddress = new Uri("https://stripe.example"));
services.AddHttpClient<IPaymentsClient, AdyenPaymentsClient>(
nameof(AdyenPaymentsClient),
client => client.BaseAddress = new Uri("https://adyen.example"));
If the implementations are deliberately meant to share one configuration, define and link them through an explicit named client so that the shared behavior is visible.
Current Detection¶
The analyzer builds a compilation-wide model of framework-owned AddHttpClient<TService, TImplementation>() registrations. It groups implicit registrations by the resolved TService symbol and reports the second and later distinct implementation types.
Detection covers registrations split across files, minimal-hosting Services receivers, configured and parameterless overloads, and namespace-qualified types. It treats a supplied string argument—including a nameof expression or compile-time constant—as an explicit name, while an optional name parameter that is omitted remains implicit. It skips registrations with an explicit name, repeated registrations of the same implementation, one-generic typed clients, unresolved type symbols, and custom extension-method lookalikes.
Code Fix¶
No automatic code fix is offered. The analyzer cannot safely decide whether the implementations require distinct names or should intentionally share an explicitly named client.
Suppression¶
Prefer making the intended relationship explicit with distinct names or a shared named-client registration. Suppress only when a custom registration abstraction has equivalent naming behavior that the analyzer cannot observe.