C# 使用工厂方法创建类型化HTTP客户端ASP.NET Core 2.1
我正在遵循有关在我的应用程序中注册HTTP客户端的指南/文档。有几项服务我需要打电话,所以我决定选择“类型化客户” 为了调用另一个服务,我需要使用OAuth——因为这是服务对服务的调用,当我获得访问令牌时,我缓存它+我设置了令牌的定期刷新。这意味着还有另一个组件C# 使用工厂方法创建类型化HTTP客户端ASP.NET Core 2.1,c#,asp.net,asp.net-core,dependency-injection,dotnet-httpclient,C#,Asp.net,Asp.net Core,Dependency Injection,Dotnet Httpclient,我正在遵循有关在我的应用程序中注册HTTP客户端的指南/文档。有几项服务我需要打电话,所以我决定选择“类型化客户” 为了调用另一个服务,我需要使用OAuth——因为这是服务对服务的调用,当我获得访问令牌时,我缓存它+我设置了令牌的定期刷新。这意味着还有另一个组件IAccessTokenCache,它为我提供了服务的访问令牌 我正在努力弄清楚的是如何注册和配置我的类型化HTTP客户机,使其同时依赖于IAccessTokenCache 我正在使用ASP.NETCore2.1(关键细节,请继续阅读)
IAccessTokenCache
,它为我提供了服务的访问令牌
我正在努力弄清楚的是如何注册和配置我的类型化HTTP客户机,使其同时依赖于IAccessTokenCache
我正在使用ASP.NETCore2.1(关键细节,请继续阅读)
HTTP客户端包装器如下所示(从:):
这就是我注册和配置客户端的方式:
services
.AddHttpClient<ServiceFooClient>(
c =>
{
c.BaseAddress = new Uri("https://www.foo.svc");
// TODO: grab particular access token from cache
c.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "...");
})
.AddHttpMessageHandler<ResponseMonitorHandler>()
.ConfigureHttpMessageHandlerBuilder(
b =>
{
var handler =
b.AdditionalHandlers.OfType<ResponseMonitorHandler>().FirstOrDefault();
if (handler != null)
{
handler.ServiceName = "Foo Service";
}
});
这可以很好地工作,除了我没有进行配置解耦-突然,专用HTTP客户端在启动中有一部分配置(基本URI,附加HTTP处理程序),在包装类中有另一部分配置(设置授权头)
未使用AddHttpClient
扩展方法(和其他方法)
我真的不需要调用HttpClientFactoryServiceCollectionExtensions.AddHttpClient(…)
-我可以自己做这些事情。但是作为一个懒惰的开发者。。。我甚至不想说完这句话。里面有很多注册信息,所以这对我来说是个大问题
升级到ASP.NET Core 2.2
与上一点相关-在2.1中,没有超负荷的AddHttpClient
(2.2:AddHttpClient(此IServiceCollection服务,Action configureClient)
),它将接受服务提供商的回调。升级到2.2可能是最好的解决方案,但我必须非常确定没有任何其他问题会被破坏(我已经知道,在HTTP上下文上获取/设置请求跟踪ID会导致BC中断)。这可能有潜在的风险,所以我首先尝试在2.1的范围内解决我的问题
比较2.1和2.2的分支:
自定义HTTP处理程序设置请求头
与我现在注册ResponseMonitorHandler
的方式相同,我可以注册HTTP处理程序,它可以访问IAccessTokenCache
,并设置请求授权头
但是,和第一种情况一样,这将使HTTP客户机的配置解耦。另外,如果我有几个不同的访问令牌,我要么需要实现几个HTTP处理程序,要么根据请求属性执行一些逻辑来决定要使用缓存中的哪个令牌
<>强>最后,问题< /强>:有没有其他的方式我没有考虑?在ASP.NET 2.1中是否有简单的解决方案?(…当然除了2.2中的复制粘贴方法之外)显然,2.1中还有另一种扩展方法,正是我所需要的
services
.AddHttpClient<ServiceFooClient>(
c =>
{
c.BaseAddress = new Uri("https://www.foo.svc");
// TODO: grab particular access token from cache
c.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "...");
})
.AddHttpMessageHandler<ResponseMonitorHandler>()
.ConfigureHttpMessageHandlerBuilder(
b =>
{
var handler =
b.AdditionalHandlers.OfType<ResponseMonitorHandler>().FirstOrDefault();
if (handler != null)
{
handler.ServiceName = "Foo Service";
}
});
// ctor
public ServiceFooClient(HttpClient httpClient, IAccessTokenCache tokenCache)
{
Client = httpClient;
Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokenCache.GetToken("Foo"));
}