HttpClientFactory používá SocketsHttpHandler jako primární obslužnou rutinu.
HttpClientFactory
umožňuje nakonfigurovat HttpMessageHandler kanál pro pojmenované a typované HttpClient objekty. Vnitřní-většina obslužné rutiny, nebo ta, která skutečně odesílá požadavek na drátu, se nazývá primární obslužná rutina. Pokud není nakonfigurovaná, byla tato obslužná rutina dříve vždy .HttpClientHandler I když je výchozí primární obslužná rutina podrobností implementace, byli na ní uživatelé, kteří na ní záviseli. Někteří uživatelé například přetypovávat primární obslužnou rutinu tak, aby HttpClientHandler
nastavily vlastnosti, jako ClientCertificatesje , UseCookiesa UseProxy.
Při této změně je výchozí primární obslužná rutina na SocketsHttpHandler platformách, které ji podporují. Na jiných platformách, například rozhraní .NET Framework, HttpClientHandler se nadále používá.
SocketsHttpHandler
nyní má také přednastavenou PooledConnectionLifetime vlastnost odpovídající hodnotě HandlerLifetime . (Odráží nejnovější hodnotu, pokud HandlerLifetime
ji uživatel nakonfiguroval).
Zavedená verze
.NET 9 Preview 6
Předchozí chování
Výchozí primární obslužná rutina byla HttpClientHandler
. Přetypování, aby HttpClientHandler
se aktualizovaly vlastnosti, které fungovaly.
services.AddHttpClient("test")
.ConfigurePrimaryHttpMessageHandler((h, _) =>
{
((HttpClientHandler)h).UseCookies = false;
});
// This worked.
var client = httpClientFactory.CreateClient("test");
Nové chování
Na platformách, kde SocketsHttpHandler
je podporovaná, je teď SocketsHttpHandler
výchozí primární obslužná rutina nastavená PooledConnectionLifetime
HandlerLifetime
na hodnotu. Přetypování na HttpClientHandler
aktualizaci vlastností vyvolá výjimku InvalidCastException.
Například stejný kód z předchozí části chování nyní vyvolá InvalidCastException:
System.InvalidCastException: Objekt typu System.Net.Http.SocketsHttpHandler nelze přetypovat na typ System.Net.Http.HttpClientHandler.
Typ zásadní změny
Tato změna je změna chování.
Důvod změny
Jedním z nejběžnějších problémů HttpClientFactory
, na které uživatelé narazili, je, když Named
se uživatel nebo Typed
klient chybně zachytí do jedné služby, nebo obecně uložené někde po dobu delší než zadanou HandlerLifetime. Vzhledem k tomu HttpClientFactory
, že takové obslužné rutiny nejde otočit, můžou nakonec nerespektovat změny DNS.
Tento problém lze zmírnit pomocí SocketsHttpHandler, který má možnost řídit PooledConnectionLifetime. HandlerLifetimePodobně jako životnost připojení ve fondu umožňuje pravidelně znovu vytvořit připojení k vyzvednutí změn DNS, ale na nižší úrovni. Klient s nastaveným PooledConnectionLifetime
nastavením se dá bezpečně používat jako jednoúčelový.
Je to bohužel snadné a zdánlivě "intuitivní" vložení Typed
klienta do jednohotonu. Je ale těžké mít nějaký druh kontroly nebo analyzátoru, aby se zajistilo HttpClient
, že se nezachytí, když neměl být zachycen. Je také obtížné vyřešit výsledné problémy. Proto jako preventivní opatření , aby se minimalizoval potenciální dopad chybných vzorů použití, SocketsHttpHandler
je teď zmírnění ve výchozím nastavení použito.
Tato změna má vliv pouze na případy, kdy koncový uživatel PrimaryHandler nenakonfiguroval vlastní (například prostřednictvím ConfigurePrimaryHttpMessageHandler<THandler>(IHttpClientBuilder)).
Doporučená akce
Existují tři možnosti, jak obejít změnu způsobující chybu:
Explicitně zadejte a nakonfigurujte primární obslužnou rutinu pro každý z vašich klientů:
services.AddHttpClient("test") .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { UseCookies = false });
Přepište výchozí primární obslužnou rutinu pro všechny klienty pomocí ConfigureHttpClientDefaults(IServiceCollection, Action<IHttpClientBuilder>):
services.ConfigureHttpClientDefaults(b => b.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { UseCookies = false }));
V akci konfigurace zkontrolujte obě
HttpClientHandler
možnosti aSocketsHttpHandler
:services.AddHttpClient("test") .ConfigurePrimaryHttpMessageHandler((h, _) => { if (h is HttpClientHandler hch) { hch.UseCookies = false; } if (h is SocketsHttpHandler shh) { shh.UseCookies = false; } });