【问题标题】:Get name HttpClient from IHttpClientFactory injected with DI从注入 DI 的 IHttpClientFactory 获取名称 HttpClient
【发布时间】:2021-03-13 15:00:18
【问题描述】:

在 Blazor 中,我设置了两个 HttpClient。一个用于我的 API,一个用于 MS Graph API。 Graph API 是新的,迫使我想办法将命名的 httpclient 注入到我的服务中。

这是 Main 中的所有代码

  public class Program
{
    public static async Task Main(string[] args)
    {
        var b = WebAssemblyHostBuilder.CreateDefault(args);
        b.RootComponents.Add<App>("app");

        var samsonApiUrl = new Uri(b.HostEnvironment.BaseAddress + "api/");

        b.Services.AddHttpClient("SamsonApi",client => 
        {
           client.BaseAddress = samsonApiUrl;
           // add jwt token to header
           // add user agent to header
        }).AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
        
        b.Services.AddTransient<GraphCustomAuthorizationMessageHandler>();
        b.Services.AddHttpClient<GraphHttpClientService>("GraphAPI",
                client => client.BaseAddress = new Uri("https://graph.microsoft.com/"))
            .AddHttpMessageHandler<GraphCustomAuthorizationMessageHandler>();
        
        b.Services.AddScoped(provider => provider.GetService<IHttpClientFactory>().CreateClient("SamsonApi"));
        b.Services.AddScoped(provider => provider.GetService<IHttpClientFactory>().CreateClient("GraphAPI"));
        
        b.Services.AddMsalAuthentication<RemoteAuthenticationState, CustomUserAccount>(options =>
        {
            b.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
            options.ProviderOptions.DefaultAccessTokenScopes.Add("1c8d4e31-97dd-4a54-8c2b-0d81e4356bf9/API.Access");
            options.UserOptions.RoleClaim = "role";
        }).AddAccountClaimsPrincipalFactory<RemoteAuthenticationState, CustomUserAccount, CustomUserFactory>();
        
        
        // add Radzen services 
        b.Services.AddScoped<DialogService>();
        b.Services.AddScoped<NotificationService>();
        b.Services.AddScoped<TooltipService>();
        // add samson component services
        b.Services.AddSingleton<FormTitleState>();
        // Add Http Services
        b.Services.Scan(scan =>
            {
                scan.FromAssemblyOf<ICustomerService>()
                    .AddClasses(classes => classes.Where(type => type.Name.EndsWith("Service")))
                    .AsMatchingInterface()
                    .WithScopedLifetime();
            });
        await b.Build().RunAsync();
    }
}

这是必须更改的代码。 它扫描了我所有的服务并注入了一个 HttpClient。 因为我现在有两个,所以我随机注入了一个客户端。 如何将命名客户端注入我的所有服务?我可以将图形 API 服务作为特例处理。

 b.Services.Scan(scan =>
            {
                scan.FromAssemblyOf<ICustomerService>()
                    .AddClasses(classes => classes.Where(type => type.Name.EndsWith("Service")))
                    .AsMatchingInterface()
                    .WithScopedLifetime();
            });

调用我的 API 的服务示例

 public class ActiveAgreementService : IActiveAgreementService
{
    private readonly HttpClient _client;
    
    public ActiveAgreementService(HttpClient client)
    {
        _client = client;
    }

    public async Task<List<ActiveAgreementDto>> GetActiveAgreements()
    {
        var lst = await _client.GetFromJsonAsync<ActiveAgreementDto[]>("ActiveAgreement");
        return lst.ToList();
    }
}

好的,最终在我的所有服务中将 HttpClient 替换为 IHttpClientFactory

public UserService(IHttpClientFactory clientFactory)
{
   _client = clientFactory.CreateClient("SamsonApi");
}

【问题讨论】:

  • 为什么要注入http客户端?您始终可以通过服务构造函数中的名称注入工厂并创建客户端。

标签: c# dependency-injection blazor-client-side scrutor


【解决方案1】:

我假设您使用的是 ASP.NET Core,但不清楚您使用的是哪个依赖注入框架。

在这种情况下,您可以让您的类依赖于IHttpClientFactory,然后使用named clients 设置配置:

// Named client like you're currently doing
b.Services.AddHttpClient("SamsonApi", client => 
{
    client.BaseAddress = samsonApiUrl;
    // add jwt token to header
    // add user agent to header
}).AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();

//...

b.Services.AddHttpClient("GraphAPI", client =>
    client.BaseAddress = new Uri("https://graph.microsoft.com/"))
    .AddHttpMessageHandler<GraphCustomAuthorizationMessageHandler>();

// And in your dependent class
public class ActiveAgreementService : IActiveAgreementService
{
    private readonly HttpClient _client;
    
    public ActiveAgreementService(IHttpClientFactory clientFac)
    {
        // Whichever one you need:
        _client = clientFac.CreateClient("SamsonApi");
        _client = clientFac.CreateClient("GraphAPI");
    }

    public async Task<List<ActiveAgreementDto>> GetActiveAgreements()
    {
        var lst = await _client.GetFromJsonAsync<ActiveAgreementDto[]>("ActiveAgreement");
        return lst.ToList();
    }
}

... 或使用typed clients 为依赖它的每个类指定实例:

// This HttpClient is only injected into ActiveAgreementService
b.Services.AddHttpClient<ActiveAgreementService>(client => 
{
    client.BaseAddress = samsonApiUrl;
    // add jwt token to header
    // add user agent to header
}).AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();

//...

// This HttpClient is only injected into GraphHttpClientService
b.Services.AddHttpClient<GraphHttpClientService>(client =>
    client.BaseAddress = new Uri("https://graph.microsoft.com/"))
    .AddHttpMessageHandler<GraphCustomAuthorizationMessageHandler>();

// And in your dependent class
public class ActiveAgreementService : IActiveAgreementService
{
    private readonly HttpClient _client;
    
    public ActiveAgreementService(HttpClient client)
    {
        _client = client;
    }

    public async Task<List<ActiveAgreementDto>> GetActiveAgreements()
    {
        var lst = await _client.GetFromJsonAsync<ActiveAgreementDto[]>("ActiveAgreement");
        return lst.ToList();
    }
}

【讨论】:

  • 谢谢。我正在使用服务提供者中的构建。我也在考虑注入 IHttpClientFactory 但我必须更改 25 个类(:我喜欢我可以创建一个新的服务类并注入它而不记得注册它
  • 不确定我是否关注。如果您需要注入不同配置的客户端,则始终必须注册它。但是当然,如​​果您有多个服务类使用HttpClient 的相同配置,那么命名客户端可能就是您想要的。从HttpClient 更改为IHttpClientFactory 应该不会花费很多时间
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-28
  • 1970-01-01
  • 1970-01-01
  • 2019-04-27
  • 1970-01-01
相关资源
最近更新 更多