IHttpClientFactory 搭配 .NET
在本文中,您將瞭解如何使用 IHttpClientFactory
來建立 HttpClient
具有各種 .NET 基礎的類型,例如相依性插入 (DI) 、記錄和設定。 此 HttpClient 型別是在 2012 年發行的 .NET Framework 4.5 中引進。 換句話說,它已經有一段時間了。 HttpClient
可用來提出 HTTP 要求,以及處理由 Uri 識別的 Web 資源之 HTTP 回應。 HTTP 通訊協定構成大部分的網際網路流量。
透過推動最佳做法的新式應用程式開發原則,IHttpClientFactory 作為處理站抽象概念,可建立具有自訂群組態的 HttpClient
執行個體。 IHttpClientFactory 是在 .NET Core 2.1 中引進。 常見的 HTTP 式 .NET 工作負載可以輕鬆利用復原和暫時性錯誤處理第三方中介軟體。
注意
如果您的應用程式需要 Cookie,則最好避免在應用程式中使用 IHttpClientFactory。 如需管理用戶端的替代方式,請參閱使用 HTTP 用戶端的指導方針。
重要
IHttpClientFactory
所建立 HttpClient
執行個體的存留期管理,與手動建立的執行個體完全不同。 策略是使用 IHttpClientFactory
所建立的「短期」用戶端,或已設定 PooledConnectionLifetime
的「長期」用戶端。 如需詳細資訊,請參閱 HttpClient 存留期管理小節以及使用 HTTP 用戶端的指導方針。
IHttpClientFactory
類型
本文中的所有樣本原始程式碼都需要使用 Microsoft.Extensions.Http
NuGet 封裝。 此外,會向免費的 {JSON} 預留位置 API 提出 HTTP GET
要求,以取得使用者 Todo
物件。
當您呼叫任何 AddHttpClient 擴充方法時,會將 IHttpClientFactory
和相關的服務新增至 IServiceCollection。 IHttpClientFactory
類型提供下列優點:
- 將
HttpClient
類別公開為 DI 就緒型別。 - 提供一個集中位置以便命名和設定邏輯
HttpClient
執行個體。 - 透過委派
HttpClient
中的處理常式來撰寫傳出中介軟體的概念。 - 提供適用於 Polly 型中介軟體的延伸模組,以利用
HttpClient
中的委派處理常式。 - 管理基礎 HttpClientHandler 執行個體的快取和存留期。 自動管理可避免在手動管理
HttpClient
存留期時,所發生的常見網域名稱系統 (DNS) 問題。 - 針對透過處理站所建立之用戶端傳送的所有要求,新增可設定的記錄體驗 (透過 ILogger)。
耗用量模式
有數種方式可將 IHttpClientFactory
用於應用程式:
最好的方法取決於應用程式的需求。
基本使用方式
若要登錄 IHttpClientFactory
請呼叫 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();
使用服務可以要求 IHttpClientFactory
作為具有 DI 的建構函式參數。 下列程式碼會使用 IHttpClientFactory
來建立 HttpClient
執行個體:
using System.Net.Http.Json;
using System.Text.Json;
using Microsoft.Extensions.Logging;
using Shared;
namespace BasicHttp.Example;
public sealed class TodoService
{
private readonly IHttpClientFactory _httpClientFactory = null!;
private readonly ILogger<TodoService> _logger = null!;
public TodoService(
IHttpClientFactory httpClientFactory,
ILogger<TodoService> logger) =>
(_httpClientFactory, _logger) = (httpClientFactory, 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 ?? Array.Empty<Todo>();
}
catch (Exception ex)
{
_logger.LogError("Error getting something fun to say: {Error}", ex);
}
return Array.Empty<Todo>();
}
}
像上述範例中使用 IHttpClientFactory
,是重構現有應用程式的好方法。 它對 HttpClient
的使用方式沒有任何影響。 在現有應用程式中建立 HttpClient
執行個體的位置,將那些項目取代為呼叫 CreateClient。
具名用戶端
在下列情況中,具名用戶端是不錯的選擇:
- 應用程式需要許多不同的
HttpClient
用法。 - 許多
HttpClient
實例都有不同的組態。
在 註冊期間可以指定具名 HttpClient
的組 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");
});
在上述程式碼中,會使用下列項目設定用戶端:
- 從
"TodoHttpClientName"
底下設定提取的名稱。 - 基底位址
https://jsonplaceholder.typicode.com/
。 "User-Agent"
標題。
您可以使用設定來指定 HTTP 用戶端名稱,這在新增和建立時有助於避免將用戶端命名錯誤。 在此範例中,使用 appsettings.json 檔案來設定 HTTP 用戶端名稱:
{
"TodoHttpClientName": "JsonPlaceholderApi"
}
可以輕易擴充此設定,並儲存更多有關 HTTP 用戶端運作方式的詳細資料。 如需詳細資訊,請參閱 .NET 中的設定。
建立用戶端
每次呼叫 CreateClient 時:
- 建立新的
HttpClient
執行個體。 - 呼叫設定動作。
若要建立具名用戶端,請將其名稱傳遞至 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 ?? Array.Empty<Todo>();
}
catch (Exception ex)
{
_logger.LogError("Error getting something fun to say: {Error}", ex);
}
return Array.Empty<Todo>();
}
}
在上述程式碼中,HTTP 要求不需要指定主機名稱。 此程式碼可以只傳遞路徑,因為已使用為用戶端設定的基底位址。
具型別用戶端
具型別用戶端:
- 提供與具名用戶端相同的功能,而不需使用字串作為索引鍵。
- 取用用戶端時提供 IntelliSense 和編譯器說明。
- 提供單一位置來設定特定的
HttpClient
並與其互動。 例如,可能會使用單一型別用戶端:- 針對單一後端端點。
- 封裝處理端點的所有邏輯。
- 使用 DI 且可在應用程式中需要之處插入。
具型別用戶端在其建構函式中接受 HttpClient
參數:
using System.Net.Http.Json;
using System.Text.Json;
using Microsoft.Extensions.Logging;
using Shared;
namespace TypedHttp.Example;
public sealed class TodoService : IDisposable
{
private readonly HttpClient _httpClient = null!;
private readonly ILogger<TodoService> _logger = null!;
public TodoService(
HttpClient httpClient,
ILogger<TodoService> logger) =>
(_httpClient, _logger) = (httpClient, logger);
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 ?? Array.Empty<Todo>();
}
catch (Exception ex)
{
_logger.LogError("Error getting something fun to say: {Error}", ex);
}
return Array.Empty<Todo>();
}
public void Dispose() => _httpClient?.Dispose();
}
在上述程式碼中:
- 當具型別用戶端新增至服務集合時,就會進行設定。
- 會將
HttpClient
指派為類別範圍的變數 (欄位),並搭配公開的 API 使用。
可以建立公開 HttpClient
功能的 API 特定方法。 例如,GetUserTodosAsync
方法會封裝程式碼,以擷取使用特定 Todo
物件。
下列程式碼會呼叫 AddHttpClient 來註冊具類型的用戶端類別:
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");
});
具型別用戶端會向 DI 註冊為暫時性。 在上述程式碼中,AddHttpClient
會將 TodoService
註冊為暫時性服務。 此註冊會使用 Factory 方法:
- 建立
HttpClient
執行個體。 - 建立
TodoService
的執行個體,並將HttpClient
的執行個體傳入其建構函式。
重要
在 singleton 服務中使用具類型用戶端可能十分危險。 如需詳細資訊,請參閱 避免單一服務中的具型別用戶端 一節。
注意
向 方法註冊具型別用戶端 AddHttpClient<TClient>
時, TClient
型別必須具有可接受參數的 HttpClient
建構函式。 此外, TClient
類型不應該個別向 DI 容器註冊。
產生的用戶端
IHttpClientFactory
可和第三方程式庫一起使用,例如 Refit。 Refit 是適用於 .NET 的 REST 程式庫。 它允許宣告式 REST API 定義,將介面方法對應至端點。 介面的實作由 RestService
動態產生,並使用 HttpClient
進行外部 HTTP 呼叫。
請考慮下列 record
類型:
namespace Shared;
public record class Todo(
int UserId,
int Id,
string Title,
bool Completed);
下列範例依賴 Refit.HttpClientFactory
NuGet 套件,而且是簡單的介面:
using Refit;
using Shared;
namespace GeneratedHttp.Example;
public interface ITodoService
{
[Get("/todos?userId={userId}")]
Task<Todo[]> GetUserTodosAsync(int userId);
}
上述 C# 介面:
- 定義名為
GetUserTodosAsync
的方法,該方法會傳回Task<Todo[]>
執行個體。 - 使用路徑和查詢字串宣告
Refit.GetAttribute
屬性給外部 API。
可以新增具型別用戶端,使用 Refit 產生實作:
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");
});
定義的介面可在需要時使用,並搭配 DI 與 Refit 所提供的實作。
提出 POST、PUT 和 DELETE 要求
在上述範例中,所有 HTTP 要求都會使用 GET
HTTP 指令動詞。 HttpClient
也支援其他 HTTP 指令動詞,包括:
POST
PUT
DELETE
PATCH
如需支援 HTTP 指令動詞的完整清單,請參閱 HttpMethod。 如需提出 HTTP 要求的詳細資訊,請參閱 使用 HttpClient 傳送要求。
下列範例顯示如何提出 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();
}
在上述程式碼中,CreateItemAsync
方法:
- 使用
System.Text.Json
將Item
參數序列化為 JSON。 這會使用 JsonSerializerOptions 的執行個體來設定序列化流程。 - 建立 StringContent 的執行個體來封裝序列化的 JSON,以在 HTTP 要求本文中傳送。
- 呼叫 PostAsync,將 JSON 內容傳送至指定的 URL。 這是新增至 HttpClient.BaseAddress 的相對 URL。
- 如果回應狀態碼未表示成功,則呼叫 EnsureSuccessStatusCode 以擲回例外狀況。
HttpClient
也支援其他型別的內容。 例如 MultipartContent 和 StreamContent。 如需完整的支援內容清單,請參閱 HttpContent。
下列範例顯示 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();
}
上述程式碼與 POST
範例非常類似。 UpdateItemAsync
方法會呼叫 PutAsync,而不是 PostAsync
。
下列範例顯示 HTTP DELETE
要求:
public async Task DeleteItemAsync(Guid id)
{
using HttpResponseMessage httpResponse =
await _httpClient.DeleteAsync($"/api/items/{id}");
httpResponse.EnsureSuccessStatusCode();
}
在上述程式碼中,DeleteItemAsync
方法會呼叫 DeleteAsync。 因為 HTTP DELETE 要求通常不包含本文,所以 DeleteAsync
方法不會提供接受 HttpContent
執行個體的多載。
若要深入了解搭配 HttpClient
使用不同的 HTTP 指令動詞,請參閱 HttpClient。
HttpClient
存留期管理
每次在 IHttpClientFactory
上呼叫 CreateClient
時,都會傳回新的 HttpClient
執行個體。 每個用戶端名稱都會建立一個 HttpClientHandler 執行個體。 處理站會管理 HttpClientHandler
執行個體的存留期。
IHttpClientFactory
會快取處理站所建立的 HttpClientHandler
執行個體,以減少資源耗用量。 建立新的 HttpClient
執行個體時,如果其存留期間尚未過期,則可能會從快取中重複使用 HttpClientHandler
執行個體。
快取處理常式非常實用,因為處理常式通常會管理自己專屬的基礎 HTTP 連線集區。 建立比所需數目更多的處理常式,可能會導致通訊端耗盡和連線延遲。 有些處理常式也會保持連線無限期地開啟,這可能導致處理常式無法對 DNS 變更回應。
預設處理常式存留時間為兩分鐘。 若要覆寫預設值,請在 IServiceCollection
上呼叫每個用戶端的 SetHandlerLifetime:
services.AddHttpClient("Named.Client")
.SetHandlerLifetime(TimeSpan.FromMinutes(5));
重要
IHttpClientFactory
所建立的 HttpClient
執行個體預計為「短期」。
HttpMessageHandler
的存留期到期時將其回收和重新建立是IHttpClientFactory
的必要動作,以確保處理常式回應 DNS 變更。HttpClient
會在建立時繫結至特定處理常式執行個體,因此應該及時要求新的HttpClient
執行個體,以確保用戶端將取得更新過的處理常式。處置「處理站所建立」的這類
HttpClient
執行個體,將不會導致通訊端耗盡,因為其處置「將不會」觸發HttpMessageHandler
的處置。IHttpClientFactory
會追蹤並處置用來建立HttpClient
執行個體 (特別是HttpMessageHandler
執行個體) 的資源,只要這些執行個體的存留期到期,而且HttpClient
不再予以使用。
長時間讓單一 HttpClient
執行個體保持運作是一種常見模式,可用作 IHttpClientFactory
的「替代方案」,不過,此模式需要額外的設定,例如 PooledConnectionLifetime
。 您可以搭配使用「長期」用戶端與 PooledConnectionLifetime
,或 IHttpClientFactory
所建立的「短期」用戶端。 如需在應用程式中使用哪項策略的相關資訊,請參閱使用 HTTP 用戶端的指導方針。
設定 HttpMessageHandler
可能需要控制用戶端使用之內部 HttpMessageHandler 的組態。
新增具名或具型別用戶端時,會傳回 IHttpClientBuilder。 ConfigurePrimaryHttpMessageHandler 擴充方法可以用來定義 IServiceCollection
上的委派。 委派是用來建立及設定該用戶端所使用的主要 HttpMessageHandler
:
.ConfigurePrimaryHttpMessageHandler(() =>
{
return new HttpClientHandler
{
AllowAutoRedirect = false,
UseDefaultCredentials = true
};
});
設定 HttClientHandler
可讓您在處理常式的各種其他屬性中指定 HttpClient
執行個體的 Proxy。 如需詳細資訊,請參閱每個用戶端的 Proxy。
其他設定
有數個額外的設定選項可用來控制 IHttpClientHandler
:
方法 | 描述 |
---|---|
AddHttpMessageHandler | 為具名 HttpClient 新增額外的訊息處理常式。 |
AddTypedClient | 設定 TClient 和與 IHttpClientBuilder 建立關聯之具名 HttpClient 之間的繫結。 |
ConfigureHttpClient | 新增將用於設定具名 HttpClient 的委派。 |
ConfigureHttpMessageHandlerBuilder | 新增用於設定訊息處理常式的委派,其會針對具名 HttpClient 使用 HttpMessageHandlerBuilder。 |
ConfigurePrimaryHttpMessageHandler | 從具名 HttpClient 的相依性插入容器中設定主要 HttpMessageHandler 。 |
RedactLoggedHeaders | 設定應在記錄前修訂其值的 HTTP 標頭名稱集合。 |
SetHandlerLifetime | 設定可以重複使用 HttpMessageHandler 執行個體的時間長度。 每個具名用戶端都可以設定自己的處理常式存留期值。 |
搭配使用 IHttpClientFactory 與 SocketsHttpHandler
的實 SocketsHttpHandler
HttpMessageHandler
作已在 .NET Core 2.1 中新增,其允許 PooledConnectionLifetime
設定。 此設定用來確保處理常式回應 DNS 變更,因此使用 SocketsHttpHandler
視為使用 IHttpClientFactory
的替代方案。 如需詳細資訊,請參閱使用 HTTP 用戶端的指導方針。
不過,可以搭配使用 SocketsHttpHandler
和 IHttpClientFactory
來改善可設定性。 使用這兩個 API,即可受益於低階 (例如,使用 LocalCertificateSelectionCallback
進行動態憑證選取) 和高階 (例如,利用 DI 整合和數個用戶端設定) 的可設定性。
使用這兩個 API:
- 將
SocketsHttpHandler
指定為PrimaryHandler
,並設定其PooledConnectionLifetime
(例如,設定為HandlerLifetime
中的先前值)。 - 因為
SocketsHttpHandler
將處理連線共用和回收,所以不再需要IHttpClientFactory
層級的處理常式回收。 您可以將HandlerLifetime
設定為Timeout.InfiniteTimeSpan
,以將其停用。
services.AddHttpClient(name)
.ConfigurePrimaryHttpMessageHandler(() =>
{
return new SocketsHttpHandler()
{
PooledConnectionLifetime = TimeSpan.FromMinutes(2)
};
})
.SetHandlerLifetime(Timeout.InfiniteTimeSpan); // Disable rotation, as it is handled by PooledConnectionLifetime
避免單一服務中具類型的用戶端
使用「具名用戶端」方式時,會將 IHttpClientFactory
插入至服務,而且每次需要 HttpClient
時都會呼叫 CreateClient 來建立 HttpClient
執行個體。
不過,使用「具類型用戶端」方式時,具類型用戶端通常是插入至服務的暫時性物件。 這可能會造成問題,因為具類型用戶端可以插入至 singleton 服務。
重要
在與 IHttpClientFactory
所建立的 HttpClient
執行個體相同的情境中,具類型用戶端應該是「短期」(如需詳細資訊,請參閱HttpClient
存留期管理)。 只要建立具類型用戶端執行個體,IHttpClientFactory
就無法對其進行控制。 如果在 singleton 中擷取具類型用戶端執行個體,則可能會防止其回應 DNS 變更,並破壞 IHttpClientFactory
的其中一個用途。
如果您需要在 singleton 服務中使用 HttpClient
執行個體,則請考慮下列選項:
- 請改用「具名用戶端」方式,並在 singleton 服務中插入
IHttpClientFactory
,然後在必要時重新建立HttpClient
執行個體。 - 如果您需要「具類型用戶端」方式,則請使用將
PooledConnectionLifetime
設定為主要處理常式的SocketsHttpHandler
。 如需搭配使用SocketsHttpHandler
與IHttpClientFactory
的詳細資訊,請參閱搭配使用 IHttpClientFactory 與 SocketsHttpHandler 小節。
IHttpClientFactory 中的訊息處理常式範圍
IHttpClientFactory
會為每個 HttpMessageHandler
執行個體建立個別 DI 範圍。 這些 DI (範圍與應用程式 DI 範圍分開,例如,ASP.NET 傳入要求範圍或使用者建立的手動 DI 範圍) ,因此它們 不會 共用範圍服務實例。 訊息處理常式範圍會繫結至處理常式存留期,而且可能會超過應用程式範圍,例如,這可能會在數個傳入要求之間重複使用具有相同已插入限定範圍相依性的相同 HttpMessageHandler
執行個體。
強烈建議使用者「不要快取 HttpMessageHandler
執行個體內的範圍相關資訊」(例如來自 HttpContext
的資料),並謹慎使用限定範圍相依性,以避免洩漏敏感性資訊。
如果您需要從訊息處理常式存取應用程式 DI 範圍,例如驗證,您會將範圍感知邏輯封裝在不同的暫時性 DelegatingHandler
中,並將它包裝在快取中的 IHttpClientFactory
實例周圍 HttpMessageHandler
。 存取任何已註冊具名用戶端的處理常式呼叫 IHttpMessageHandlerFactory.CreateHandler 。 在此情況下,您會使用建構的處理常式自行建立 HttpClient
實例。
下列範例示範如何使用範圍感知 DelegatingHandler
建立 HttpClient
:
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);
進一步的因應措施可以遵循擴充方法,以註冊範圍感知 DelegatingHandler
並覆寫暫時性服務存取目前應用程式範圍的預設 IHttpClientFactory
註冊:
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;
}
如需詳細資訊,請參閱完整範例。
另請參閱
.NET feedback
The .NET documentation is open source. Provide feedback here.
意見反應
提交並檢視相關的意見反應