IHttpClientFactory and typed HTTP clients for .NET 10 applications. Covers named/typed/keyed clients, DelegatingHandlers, resilience with Microsoft.Extensions.Http.Resilience, and testing patterns. Load this skill when configuring HTTP clients, adding retry/circuit breaker policies, or when the user mentions "HttpClient", "IHttpClientFactory", "AddHttpClient", "typed client", "named client", "DelegatingHandler", "resilience", "retry", "circuit breaker", "hedging", "Polly", "AddStandardResilienceHandler", "socket exhaustion", or "Refit".
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
IHttpClientFactory and typed HTTP clients for .NET 10 applications. Covers named/typed/keyed clients, DelegatingHandlers, resilience with Microsoft.Extensions.Http.Resilience, and testing patterns. Load this skill when configuring HTTP clients, adding retry/circuit breaker policies, or when the user mentions "HttpClient", "IHttpClientFactory", "AddHttpClient", "typed client", "named client", "DelegatingHandler", "resilience", "retry", "circuit breaker", "hedging", "Polly", "AddStandardResilienceHandler", "socket exhaustion", or "Refit".
HttpClient Factory
Core Principles
Never new HttpClient() per request — Raw HttpClient creation causes socket exhaustion under load and ignores DNS changes. Use IHttpClientFactory to manage handler lifetimes.
Keyed clients over typed clients — Keyed DI (.AddAsKeyed()) is the recommended pattern in .NET 10. Typed clients captured in singletons silently break handler rotation.
Resilience is not optional — Every external HTTP call needs retry, circuit breaker, and timeout. AddStandardResilienceHandler() provides sensible defaults in one line.
DelegatingHandlers for cross-cutting concerns — Auth tokens, correlation IDs, and logging belong in the handler pipeline, not scattered across service methods.
publicsealedclassMockHttpHandler(
HttpStatusCode statusCode,
string content) : HttpMessageHandler
{
protectedoverride Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
return Task.FromResult(new HttpResponseMessage(statusCode)
{
Content = new StringContent(content, Encoding.UTF8, "application/json")
});
}
}
// In testvar handler = new MockHttpHandler(HttpStatusCode.OK, """{"id":1}""");
var client = new HttpClient(handler) { BaseAddress = new Uri("https://api.test/") };
var service = new MyService(client);
Anti-patterns
Don't Create HttpClient Per Request
// BAD — socket exhaustion under load, ignores DNS changespublicasync Task<string> GetDataAsync()
{
usingvar client = new HttpClient();
returnawait client.GetStringAsync("https://api.example.com/data");
}
// GOOD — factory-managedpublicasync Task<string> GetDataAsync(CancellationToken ct)
{
var client = factory.CreateClient("api");
returnawait client.GetStringAsync("https://api.example.com/data", ct);
}
Don't Capture Typed Clients in Singletons
// BAD — transient HttpClient captured by singleton defeats handler rotation
services.AddSingleton<MySingletonService>();
services.AddHttpClient<MySingletonService>();
// GOOD — use keyed client or IHttpClientFactory in singletons
services.AddSingleton<MySingletonService>();
services.AddHttpClient("myservice").AddAsKeyed(ServiceLifetime.Singleton);
Don't Mutate DefaultRequestHeaders on Shared Clients
// BAD — not thread-safe
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", token);
// GOOD — use DelegatingHandler or per-request HttpRequestMessageusingvar request = new HttpRequestMessage(HttpMethod.Get, "/api/data");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
await httpClient.SendAsync(request, ct);
Don't Forget CancellationToken
// BAD — no cancellation supportvar result = await httpClient.GetFromJsonAsync<Order>("/orders/1");
// GOOD — always pass CancellationTokenvar result = await httpClient.GetFromJsonAsync<Order>("/orders/1", cancellationToken);
Don't Stack Multiple Resilience Handlers
// BAD — conflicting resilience strategies
builder.AddStandardResilienceHandler();
builder.AddStandardHedgingHandler();
// GOOD — one standard handler, or a custom pipeline
builder.AddStandardResilienceHandler();
Decision Guide
Scenario
Recommendation
New .NET 10 project
Keyed clients with AddAsKeyed()
Singleton service needs HttpClient
Named client via IHttpClientFactory or keyed singleton
External API calls
AddStandardResilienceHandler() on every client
Auth token injection
DelegatingHandler registered with AddHttpMessageHandler
Hedging (parallel requests)
AddStandardHedgingHandler() for latency-sensitive calls
Non-idempotent methods
DisableForUnsafeHttpMethods() on retry options
Custom retry logic
AddResilienceHandler("name", builder => ...)
Connection pooling control
UseSocketsHttpHandler with PooledConnectionLifetime
API client generation
Refit with AddRefitClient<T>()
Integration testing
Custom HttpMessageHandler or MockHttpMessageHandler