IHttpClientFactory s .NET
V tomto článku se dozvíte, jak pomocí IHttpClientFactory
rozhraní vytvářet HttpClient
typy s různými základy .NET, jako je injektáž závislostí (DI), protokolování a konfigurace. Typ HttpClient byl zaveden v rozhraní .NET Framework 4.5, který byl vydán v roce 2012. Jinými slovy, je to už nějakou dobu. HttpClient
slouží k vytváření požadavků HTTP a zpracování odpovědí HTTP z webových prostředků identifikovaných pomocí Uri. Protokol HTTP tvoří velkou většinu veškerého internetového provozu.
Díky moderním principům vývoje aplikací, které řídí osvědčené postupy, IHttpClientFactory slouží jako abstrakce továrny, která může vytvářet HttpClient
instance s vlastními konfiguracemi. IHttpClientFactory byla zavedena v .NET Core 2.1. Běžné úlohy .NET založené na protokolu HTTP můžou snadno využívat odolný a přechodný middleware pro zpracování chyb třetích stran.
Poznámka:
Pokud vaše aplikace vyžaduje soubory cookie, může být lepší se vyhnout použití IHttpClientFactory ve vaší aplikaci. Alternativní způsoby správy klientů najdete v tématu Pokyny pro používání klientů HTTP.
Důležité
Správa životnosti instancí vytvořených HttpClient
IHttpClientFactory
ručně se liší od instancí vytvořených ručně. Strategie jsou použití krátkodobých klientů vytvořených klienty IHttpClientFactory
nebo dlouhodobých klientů s PooledConnectionLifetime
nastavením. Další informace najdete v části Správa životnosti HttpClient a pokyny pro používání klientů HTTP.
Typ IHttpClientFactory
Veškerý ukázkový zdrojový kód uvedený v tomto článku vyžaduje instalaci Microsoft.Extensions.Http
balíčku NuGet. Příklady kódu navíc ukazují použití požadavků HTTP GET
k načtení uživatelských Todo
objektů z bezplatného zástupného rozhraní API {JSON}.
Když voláte některou AddHttpClient z metod rozšíření, přidáváte do IHttpClientFactory
ní IServiceCollectionslužby a související služby . Typ IHttpClientFactory
nabízí následující výhody:
HttpClient
Zveřejňuje třídu jako typ připravený k di-ready.- Poskytuje centrální umístění pro pojmenování a konfiguraci logických instancí
HttpClient
. - Kodifikuje koncept odchozího middlewaru prostřednictvím delegování obslužných rutin v
HttpClient
. - Poskytuje rozšiřující metody pro Polly založený middleware, které využívají delegování obslužných rutin v
HttpClient
. - Spravuje ukládání do mezipaměti a životnost základních HttpClientHandler instancí. Automatická správa zabraňuje běžným problémům dns (Domain Name System), ke kterým dochází při ruční správě
HttpClient
životnosti. - Přidá konfigurovatelné protokolování (prostřednictvím ILogger) pro všechny požadavky odeslané prostřednictvím klientů vytvořených továrnou.
Spotřeby
V aplikaci můžete použít několik způsobů IHttpClientFactory
:
Nejlepší přístup závisí na požadavcích aplikace.
Základní použití
Chcete-li zaregistrovat IHttpClientFactory
, zavolejte AddHttpClient
:
using Shared;
using BasicHttp.Example;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHttpClient();
builder.Services.AddTransient<TodoService>();
using IHost host = builder.Build();
Využívání služeb může vyžadovat parametr konstruktoru IHttpClientFactory
s DI. Následující kód používá IHttpClientFactory
k vytvoření HttpClient
instance:
using System.Net.Http.Json;
using System.Text.Json;
using Microsoft.Extensions.Logging;
using Shared;
namespace BasicHttp.Example;
public sealed class TodoService(
IHttpClientFactory httpClientFactory,
ILogger<TodoService> logger)
{
public async Task<Todo[]> GetUserTodosAsync(int userId)
{
// Create the client
using HttpClient client = httpClientFactory.CreateClient();
try
{
// Make HTTP GET request
// Parse JSON response deserialize into Todo types
Todo[]? todos = await client.GetFromJsonAsync<Todo[]>(
$"https://jsonplaceholder.typicode.com/todos?userId={userId}",
new JsonSerializerOptions(JsonSerializerDefaults.Web));
return todos ?? [];
}
catch (Exception ex)
{
logger.LogError("Error getting something fun to say: {Error}", ex);
}
return [];
}
}
Použití IHttpClientFactory
podobné jako v předchozím příkladu je dobrým způsobem, jak refaktorovat existující aplikaci. Nemá žádný vliv na způsob HttpClient
použití. V místech, kde HttpClient
se instance vytvářejí v existující aplikaci, nahraďte tyto výskyty voláními CreateClient.
Pojmenovaní klienti
Pojmenovaní klienti jsou dobrou volbou, když:
- Aplikace vyžaduje mnoho různých použití
HttpClient
. - Mnoho
HttpClient
instancí má různé konfigurace.
Konfiguraci pojmenovaného HttpClient
názvu lze zadat během registrace v IServiceCollection
:
using Shared;
using NamedHttp.Example;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
string? httpClientName = builder.Configuration["TodoHttpClientName"];
ArgumentException.ThrowIfNullOrEmpty(httpClientName);
builder.Services.AddHttpClient(
httpClientName,
client =>
{
// Set the base address of the named client.
client.BaseAddress = new Uri("https://jsonplaceholder.typicode.com/");
// Add a user-agent default request header.
client.DefaultRequestHeaders.UserAgent.ParseAdd("dotnet-docs");
});
V předchozím kódu je klient nakonfigurovaný takto:
- Název, který se načítá z konfigurace pod položkou
"TodoHttpClientName"
. - Základní adresa
https://jsonplaceholder.typicode.com/
. - Záhlaví
"User-Agent"
.
Konfiguraci můžete použít k určení názvů klientů HTTP, což je užitečné, abyste se vyhnuli nesprávnému přejmenování klientů při přidávání a vytváření. V tomto příkladu se k konfiguraci názvu klienta HTTP používá soubor appsettings.json :
{
"TodoHttpClientName": "JsonPlaceholderApi"
}
Tuto konfiguraci můžete snadno rozšířit a uložit další podrobnosti o tom, jak má klient HTTP fungovat. Další informace naleznete v tématu Konfigurace v .NET.
Vytvoření klienta
Pokaždé CreateClient se volá:
- Vytvoří se nová instance
HttpClient
. - Volá se akce konfigurace.
Pokud chcete vytvořit pojmenovaného klienta, předejte jeho název do CreateClient
:
using System.Net.Http.Json;
using System.Text.Json;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Shared;
namespace NamedHttp.Example;
public sealed class TodoService
{
private readonly IHttpClientFactory _httpClientFactory = null!;
private readonly IConfiguration _configuration = null!;
private readonly ILogger<TodoService> _logger = null!;
public TodoService(
IHttpClientFactory httpClientFactory,
IConfiguration configuration,
ILogger<TodoService> logger) =>
(_httpClientFactory, _configuration, _logger) =
(httpClientFactory, configuration, logger);
public async Task<Todo[]> GetUserTodosAsync(int userId)
{
// Create the client
string? httpClientName = _configuration["TodoHttpClientName"];
using HttpClient client = _httpClientFactory.CreateClient(httpClientName ?? "");
try
{
// Make HTTP GET request
// Parse JSON response deserialize into Todo type
Todo[]? todos = await client.GetFromJsonAsync<Todo[]>(
$"todos?userId={userId}",
new JsonSerializerOptions(JsonSerializerDefaults.Web));
return todos ?? [];
}
catch (Exception ex)
{
_logger.LogError("Error getting something fun to say: {Error}", ex);
}
return [];
}
}
V předchozím kódu požadavek HTTP nemusí zadávat název hostitele. Kód může předat pouze cestu, protože se používá základní adresa nakonfigurovaná pro klienta.
Typoví klienti
Typoví klienti:
- Poskytněte stejné možnosti jako pojmenovaní klienti bez nutnosti používat řetězce jako klíče.
- Poskytnutí nápovědy IntelliSense a kompilátoru při využívání klientů
- Zadejte jedno umístění pro konfiguraci a interakci s určitým
HttpClient
. Může se například použít jeden typ klienta:- Pro jeden back-endový koncový bod.
- Zapouzdření veškeré logiky, která se zabývá koncovým bodem.
- Pracujte s DI a můžete je v aplikaci vsunou tam, kde je to potřeba.
Zadaný klient přijímá parametr v jeho konstruktoru HttpClient
:
using System.Net.Http.Json;
using System.Text.Json;
using Microsoft.Extensions.Logging;
using Shared;
namespace TypedHttp.Example;
public sealed class TodoService(
HttpClient httpClient,
ILogger<TodoService> logger) : IDisposable
{
public async Task<Todo[]> GetUserTodosAsync(int userId)
{
try
{
// Make HTTP GET request
// Parse JSON response deserialize into Todo type
Todo[]? todos = await httpClient.GetFromJsonAsync<Todo[]>(
$"todos?userId={userId}",
new JsonSerializerOptions(JsonSerializerDefaults.Web));
return todos ?? [];
}
catch (Exception ex)
{
logger.LogError("Error getting something fun to say: {Error}", ex);
}
return [];
}
public void Dispose() => httpClient?.Dispose();
}
V předchozím kódu:
- Konfigurace se nastaví při přidání zadaného klienta do kolekce služeb.
- Je
HttpClient
přiřazena jako proměnná s oborem třídy (pole) a používá se s vystavenými rozhraními API.
Metody specifické pro rozhraní API je možné vytvořit, které zpřístupňují HttpClient
funkce. GetUserTodosAsync
Například metoda zapouzdřuje kód pro načtení objektů specifických pro Todo
uživatele.
Následující volání AddHttpClient kódu pro registraci typové třídy klienta:
using Shared;
using TypedHttp.Example;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHttpClient<TodoService>(
client =>
{
// Set the base address of the typed client.
client.BaseAddress = new Uri("https://jsonplaceholder.typicode.com/");
// Add a user-agent default request header.
client.DefaultRequestHeaders.UserAgent.ParseAdd("dotnet-docs");
});
Zadaný klient je zaregistrovaný jako přechodný s DI. V předchozím kódu AddHttpClient
se zaregistruje TodoService
jako přechodná služba. Tato registrace používá metodu továrny k:
- Vytvořte instanci
HttpClient
. - Vytvoření instance ,
TodoService
předání instanceHttpClient
do jeho konstruktoru.
Důležité
Používání typových klientů v jednoúčelových službách může být nebezpečné. Další informace najdete v části Vyhnout se typed klientům v části Singleton Services .
Poznámka:
Při registraci zadaného klienta v AddHttpClient<TClient>
metodě TClient
musí mít typ konstruktor, který přijímá jako HttpClient
parametr. Kromě toho TClient
by se typ neměl registrovat u kontejneru DI samostatně, protože to povede k pozdější registraci přepsání bývalé registrace.
Vygenerované klienty
IHttpClientFactory
lze použít v kombinaci s knihovnami třetích stran, jako je například Refit. Refit je knihovna REST pro .NET. Umožňuje deklarativní definice rozhraní REST API, metody mapování rozhraní na koncové body. Implementace rozhraní se generuje dynamicky RestService
pomocí , pomocí HttpClient
k provedení externích volání HTTP.
Zvažte následující record
typ:
namespace Shared;
public record class Todo(
int UserId,
int Id,
string Title,
bool Completed);
Následující příklad spoléhá na Refit.HttpClientFactory
balíček NuGet a je to jednoduché rozhraní:
using Refit;
using Shared;
namespace GeneratedHttp.Example;
public interface ITodoService
{
[Get("/todos?userId={userId}")]
Task<Todo[]> GetUserTodosAsync(int userId);
}
Předchozí rozhraní jazyka C#:
- Definuje metodu s názvem
GetUserTodosAsync
, která vracíTask<Todo[]>
instanci. - Deklaruje
Refit.GetAttribute
atribut s cestou a řetězcem dotazu pro externí rozhraní API.
Typový klient je možné přidat pomocí nástroje Refit k vygenerování implementace:
using GeneratedHttp.Example;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Refit;
using Shared;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddRefitClient<ITodoService>()
.ConfigureHttpClient(client =>
{
// Set the base address of the named client.
client.BaseAddress = new Uri("https://jsonplaceholder.typicode.com/");
// Add a user-agent default request header.
client.DefaultRequestHeaders.UserAgent.ParseAdd("dotnet-docs");
});
Definované rozhraní lze v případě potřeby využívat s implementací, kterou poskytuje DI a Refit.
Vytváření požadavků POST, PUT a DELETE
V předchozích příkladech používají GET
všechny požadavky HTTP příkaz HTTP. HttpClient
také podporuje další příkazy HTTP, včetně:
POST
PUT
DELETE
PATCH
Úplný seznam podporovaných příkazů HTTP najdete v tématu HttpMethod. Další informace o vytváření požadavků HTTP naleznete v tématu Odeslání požadavku pomocí HttpClient.
Následující příklad ukazuje, jak vytvořit požadavek HTTP POST
:
public async Task CreateItemAsync(Item item)
{
using StringContent json = new(
JsonSerializer.Serialize(item, new JsonSerializerOptions(JsonSerializerDefaults.Web)),
Encoding.UTF8,
MediaTypeNames.Application.Json);
using HttpResponseMessage httpResponse =
await httpClient.PostAsync("/api/items", json);
httpResponse.EnsureSuccessStatusCode();
}
V předchozím kódu CreateItemAsync
metoda:
- Serializuje
Item
parametr do FORMÁTU JSON pomocíSystem.Text.Json
. To používá instanci JsonSerializerOptions ke konfiguraci procesu serializace. - Vytvoří instanci pro zabalení serializovaného StringContent JSON pro odeslání v těle požadavku HTTP.
- Volání PostAsync pro odeslání obsahu JSON na zadanou adresu URL Toto je relativní adresa URL, která se přidá do HttpClient.BaseAddress.
- Volání EnsureSuccessStatusCode vyvolání výjimky, pokud stavový kód odpovědi nezjistí úspěch.
HttpClient
podporuje také jiné typy obsahu. Příklad: MultipartContent a StreamContent. Úplný seznam podporovaného obsahu najdete v tématu HttpContent.
Následující příklad ukazuje požadavek HTTP PUT
:
public async Task UpdateItemAsync(Item item)
{
using StringContent json = new(
JsonSerializer.Serialize(item, new JsonSerializerOptions(JsonSerializerDefaults.Web)),
Encoding.UTF8,
MediaTypeNames.Application.Json);
using HttpResponseMessage httpResponse =
await httpClient.PutAsync($"/api/items/{item.Id}", json);
httpResponse.EnsureSuccessStatusCode();
}
Předchozí kód je velmi podobný příkladu POST
. Metoda UpdateItemAsync
volá PutAsync místo PostAsync
.
Následující příklad ukazuje požadavek HTTP DELETE
:
public async Task DeleteItemAsync(Guid id)
{
using HttpResponseMessage httpResponse =
await httpClient.DeleteAsync($"/api/items/{id}");
httpResponse.EnsureSuccessStatusCode();
}
V předchozím kódu DeleteItemAsync
metoda volá DeleteAsync. Vzhledem k tomu, že požadavky HTTP DELETE obvykle neobsahují žádný text, DeleteAsync
metoda neposkytuje přetížení, které přijímá instanci HttpContent
.
Další informace o použití různých příkazů HTTP s HttpClient
, viz HttpClient.
HttpClient
správa životnosti
Nová HttpClient
instance se vrátí pokaždé, když CreateClient
je volána na IHttpClientFactory
. Pro každý název klienta se vytvoří jedna HttpClientHandler instance. Továrna spravuje životnosti HttpClientHandler
instancí.
IHttpClientFactory
HttpClientHandler
ukládá instance vytvořené továrnou do mezipaměti, aby se snížila spotřeba prostředků. Instance HttpClientHandler
může být znovu použita z mezipaměti při vytváření nové HttpClient
instance, pokud jeho životnost nevypršela.
Ukládání obslužných rutin do mezipaměti je žádoucí, protože každá obslužná rutina obvykle spravuje svůj vlastní základní fond připojení HTTP. Vytvoření více obslužných rutin, než je potřeba, může vést k vyčerpání soketů a zpoždění připojení. Některé obslužné rutiny také trvale udržují připojení otevřená, což může obslužné rutině zabránit v reakci na změny DNS.
Výchozí životnost obslužné rutiny je dvě minuty. Pokud chcete přepsat výchozí hodnotu, zavolejte SetHandlerLifetime pro každého klienta na :IServiceCollection
services.AddHttpClient("Named.Client")
.SetHandlerLifetime(TimeSpan.FromMinutes(5));
Důležité
HttpClient
Instance vytvořené pomocí IHttpClientFactory
jsou určeny k krátkodobému použití.
Recyklace a opětovné vytvoření
HttpMessageHandler
po vypršení jejich životnosti je nezbytné,IHttpClientFactory
aby obslužné rutiny reagovaly na změny DNS.HttpClient
je svázaný s konkrétní instancí obslužné rutiny při jeho vytvoření, takže novéHttpClient
instance by měly být požadovány včas, aby se zajistilo, že klient získá aktualizovanou obslužnou rutinu.Vyřazení takových
HttpClient
instancí vytvořených továrnou nebude vést k vyčerpání soketů, protože jeho odstranění nespustí odstraněníHttpMessageHandler
.IHttpClientFactory
sleduje a odstraňuje prostředky používané k vytvářeníHttpClient
instancí, konkrétněHttpMessageHandler
instancí, jakmile jejich životnost vyprší a už je nepoužíváHttpClient
.
Udržování jedné HttpClient
instance naživu po dlouhou dobu je běžný vzor, který lze použít jako alternativu IHttpClientFactory
k , ale tento vzor vyžaduje další nastavení, například PooledConnectionLifetime
. Můžete použít dlouhodobé klienty s PooledConnectionLifetime
nebo krátkodobými klienty vytvořenými .IHttpClientFactory
Informace o tom, jakou strategii použít ve vaší aplikaci, najdete v tématu Pokyny pro používání klientů HTTP.
Konfigurace HttpMessageHandler
Může být nutné řídit konfiguraci vnitřního HttpMessageHandler prostředí používaného klientem.
Vrátí IHttpClientBuilder se při přidávání pojmenovaných nebo zadaných klientů. Metodu ConfigurePrimaryHttpMessageHandler rozšíření lze použít k definování delegáta na .IServiceCollection
Delegát se používá k vytvoření a konfiguraci primárního HttpMessageHandler
klienta, který tento klient používá:
.ConfigurePrimaryHttpMessageHandler(() =>
{
return new HttpClientHandler
{
AllowAutoRedirect = false,
UseDefaultCredentials = true
};
});
Konfigurace HttClientHandler
umožňuje zadat proxy pro HttpClient
instanci mezi různými dalšími vlastnostmi obslužné rutiny. Další informace najdete v tématu Proxy na klienta.
Další konfigurace
Existuje několik dalších možností konfigurace pro řízení IHttpClientHandler
:
metoda | Popis |
---|---|
AddHttpMessageHandler | Přidá další obslužnou rutinu zprávy pro pojmenovanou HttpClient . |
AddTypedClient | Konfiguruje vazbu mezi TClient a pojmenovanou HttpClient přidruženou k sadě IHttpClientBuilder . |
ConfigureHttpClient | Přidá delegáta, který se použije ke konfiguraci pojmenovaného HttpClient . |
ConfigurePrimaryHttpMessageHandler | Nakonfiguruje primární HttpMessageHandler kontejner injektáže závislostí pro pojmenovanou HttpClient . |
RedactLoggedHeaders | Nastaví kolekci názvů hlaviček HTTP, pro které mají být hodnoty před protokolováním upraveny. |
SetHandlerLifetime | Nastaví dobu, po kterou HttpMessageHandler může být instance znovu použita. Každý pojmenovaný klient může mít svou vlastní nakonfigurovanou hodnotu životnosti obslužné rutiny. |
UseSocketsHttpHandler | Nakonfiguruje novou nebo dříve přidanou SocketsHttpHandler instanci z kontejneru injektáže závislostí tak, aby byla použita jako primární obslužná rutina pro pojmenovanou HttpClient . (pouze .NET 5+ |
Použití IHttpClientFactory společně se SoketsHttpHandler
Implementace SocketsHttpHandler
HttpMessageHandler
byla přidána v .NET Core 2.1, což umožňuje PooledConnectionLifetime
konfiguraci. Toto nastavení slouží k zajištění toho, aby obslužná rutina reagovala na změny DNS, takže použití SocketsHttpHandler
se považuje za alternativu k použití IHttpClientFactory
. Další informace najdete v tématu Pokyny pro používání klientů HTTP.
SocketsHttpHandler
Dá se ale použít společně a IHttpClientFactory
zlepšit konfigurovatelnost. Pomocí obou těchto rozhraní API můžete využít možnosti konfigurace na nízké úrovni (například pro LocalCertificateSelectionCallback
výběr dynamického certifikátu) a vysokou úroveň (například využití integrace DI a několika konfigurací klientů).
Použití obou rozhraní API:
- Zadejte
SocketsHttpHandler
jakoPrimaryHandler
via ConfigurePrimaryHttpMessageHandlernebo UseSocketsHttpHandler (pouze .NET 5+). - Nastavte SocketsHttpHandler.PooledConnectionLifetime na základě intervalu, který očekáváte, že se DNS aktualizuje, například na hodnotu, která byla dříve v
HandlerLifetime
. - (Volitelné) Vzhledem k tomu
SocketsHttpHandler
, že bude zpracovávat sdružování a recyklaci připojení, recyklace obslužné rutinyIHttpClientFactory
na úrovni už není nutná. Můžete ho zakázat nastavenímHandlerLifetime
naTimeout.InfiniteTimeSpan
.
services.AddHttpClient(name)
.UseSocketsHttpHandler((handler, _) =>
handler.PooledConnectionLifetime = TimeSpan.FromMinutes(2)) // Recreate connection every 2 minutes
.SetHandlerLifetime(Timeout.InfiniteTimeSpan); // Disable rotation, as it is handled by PooledConnectionLifetime
V předchozím příkladu byly pro ilustraci vybrány libovolně 2 minuty, které odpovídají výchozí HandlerLifetime
hodnotě. Měli byste zvolit hodnotu na základě očekávané frekvence DNS nebo jiných změn sítě. Další informace najdete v části chování DNS v HttpClient
pokynech a v části Poznámky v PooledConnectionLifetime dokumentaci k rozhraní API.
Vyhněte se typem klientů v jednoúčelových službách
Při použití pojmenovaného klientského přístupu se IHttpClientFactory
vloží do služeb a HttpClient
instance se vytvoří voláním CreateClient pokaždé, když HttpClient
je potřeba.
Při přístupu typu klienta jsou však typoví klienti přechodnými objekty obvykle vloženými do služeb. To může způsobit problém, protože typový klient lze vložit do jednoúčelové služby.
Důležité
Očekává se, že typoví klienti budou krátkodobě shodní s HttpClient
instancemi vytvořenými IHttpClientFactory
(další informace najdete v tématu HttpClient
správa životnosti). Jakmile se vytvoří zatypovaná instance klienta, IHttpClientFactory
nemá nad ní žádnou kontrolu. Pokud je zachytává zaznamenaná instance typu klienta v jednomtonu, může zabránit tomu, aby reagovala na změny DNS, a porazit jeden z účelů IHttpClientFactory
.
Pokud potřebujete používat HttpClient
instance ve službě singleton, zvažte následující možnosti:
- Místo toho použijte pojmenovaný klientský přístup, vkážou
IHttpClientFactory
se do služby Singleton a v případě potřeby znovu vytvoříHttpClient
instance. - Pokud potřebujete přístup typu klienta , použijte
SocketsHttpHandler
s nakonfigurovanouPooledConnectionLifetime
primární obslužnou rutinou. Další informace o použití sSocketsHttpHandler
IHttpClientFactory
, naleznete v části Použití IHttpClientFactory společně s SocketsHttpHandler.
Obory obslužné rutiny zpráv v IHttpClientFactory
IHttpClientFactory
vytvoří pro každou HttpMessageHandler
instanci samostatný obor DI. Tyto obory DI jsou oddělené od oborů DI aplikací (například ASP.NET rozsah příchozích požadavků nebo uživatelem vytvořený ruční obor DI), takže nebudou sdílet instance služby s vymezeným oborem. Obory obslužné rutiny zpráv jsou svázané s životností obslužné rutiny a můžou vést k obnovení rozsahů aplikace, což může vést například k opakovanému použití stejné instance se stejnými HttpMessageHandler
vloženými vymezenými závislostmi mezi několika příchozími požadavky.
Uživatelé důrazně nedoporučuje ukládat informace související s oborem (například data z HttpContext
) do mezipaměti v HttpMessageHandler
instancích a používat vymezené závislosti s opatrností, aby nedošlo k úniku citlivých informací.
Pokud potřebujete přístup k oboru DI aplikace z obslužné rutiny zprávy, jako příklad byste zapouzdřili logiku podporující obor v samostatné přechodném DelegatingHandler
objektu IHttpClientFactory
a zabalili ji kolem HttpMessageHandler
instance z mezipaměti. Přístup k volání IHttpMessageHandlerFactory.CreateHandler obslužné rutiny pro všechny registrované pojmenované klienty. V takovém případě byste sami vytvořili HttpClient
instanci pomocí vytvořené obslužné rutiny.
Následující příklad ukazuje vytvoření s HttpClient
podporou oboru DelegatingHandler
:
if (scopeAwareHandlerType != null)
{
if (!typeof(DelegatingHandler).IsAssignableFrom(scopeAwareHandlerType))
{
throw new ArgumentException($"""
Scope aware HttpHandler {scopeAwareHandlerType.Name} should
be assignable to DelegatingHandler
""");
}
// Create top-most delegating handler with scoped dependencies
scopeAwareHandler = (DelegatingHandler)_scopeServiceProvider.GetRequiredService(scopeAwareHandlerType); // should be transient
if (scopeAwareHandler.InnerHandler != null)
{
throw new ArgumentException($"""
Inner handler of a delegating handler {scopeAwareHandlerType.Name} should be null.
Scope aware HttpHandler should be registered as Transient.
""");
}
}
// Get or create HttpMessageHandler from HttpClientFactory
HttpMessageHandler handler = _httpMessageHandlerFactory.CreateHandler(name);
if (scopeAwareHandler != null)
{
scopeAwareHandler.InnerHandler = handler;
handler = scopeAwareHandler;
}
HttpClient client = new(handler);
Další alternativní řešení může následovat s metodou rozšíření pro registraci výchozí registrace s podporou DelegatingHandler
oboru a přepsání výchozí IHttpClientFactory
registrace přechodnou službou s přístupem k aktuálnímu oboru aplikace:
public static IHttpClientBuilder AddScopeAwareHttpHandler<THandler>(
this IHttpClientBuilder builder) where THandler : DelegatingHandler
{
builder.Services.TryAddTransient<THandler>();
if (!builder.Services.Any(sd => sd.ImplementationType == typeof(ScopeAwareHttpClientFactory)))
{
// Override default IHttpClientFactory registration
builder.Services.AddTransient<IHttpClientFactory, ScopeAwareHttpClientFactory>();
}
builder.Services.Configure<ScopeAwareHttpClientFactoryOptions>(
builder.Name, options => options.HttpHandlerType = typeof(THandler));
return builder;
}
Další informace najdete v úplném příkladu.