C# 使用工厂方法创建类型化HTTP客户端ASP.NET Core 2.1

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(关键细节,请继续阅读)

我正在遵循有关在我的应用程序中注册HTTP客户端的指南/文档。有几项服务我需要打电话,所以我决定选择“类型化客户”

为了调用另一个服务,我需要使用OAuth——因为这是服务对服务的调用,当我获得访问令牌时,我缓存它+我设置了令牌的定期刷新。这意味着还有另一个组件
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"));
}