c# - ASP.NET Core 类型化客户端中的 IHttpClientFactory

标签 c# asp.net-core dependency-injection dotnet-httpclient asp.net-core-2.1

当我尝试使用 HttpClient 的类型化客户端时收到错误消息,如下所述: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-2.2

这是我的设置:

启动.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    services.AddDefaultAWSOptions(Configuration.GetAWSOptions());

    services.AddHttpClient<IPStackService>(c =>
    {
        c.BaseAddress = new Uri(Configuration["IPStackURL"]);
    });

    services.AddHttpContextAccessor();

    services.AddTransient<IIPStackService, IPStackService>();
}

Controller :

[Route("api/[controller]")]
    [ApiController]
    public class RenderController : ControllerBase
    {
        private IConfiguration _configuration;
        private readonly ILogger _logger;
        private IIPStackService _ipMetaDataService;

        public RenderController(IConfiguration configuration,
                                ILogger<RenderController> logger,
                                IIPStackService ipStackService)
        {
            _configuration = configuration;
            _ipStackService = ipStackService;
            _logger = logger;
        }

        [HttpGet]
        [ProducesResponseType(StatusCodes.Status200OK)]
        [Produces("text/plain")]
        public async Task<ActionResult> GetAsync(string hostId, string clientUtc)
        {
            var ip = Common.ResolveIPAddress(HttpContext);

            var ipMetaData = await _ipStackService.GetByIPAsync(ip, _configuration["AccessKey"]);

            // removed for clarity

            return allowed ? Ok(true) : Ok(null);
        }
    }

服务:

public class IPStackService : IIPStackService
{
    private readonly ILogger _logger;
    private readonly HttpClient _httpClient;

    public IPStackService(ILogger<IPStackService> logger, HttpClient client)
    {
        _logger = logger;
        _httpClient = client;
    }

    public async Task<IPMetaDataModel> GetByIPAsync(string ip, string accessKey)
    {
        var ipMetaData = new IPMetaDataModel();

        var response = await _httpClient.GetAsync($"/{ip}?access_key={accessKey}");
        response.EnsureSuccessStatusCode();

        // removed for clarity

        return ipMetaData;
    }
}

收到错误:

An unhandled exception occurred while processing the request. InvalidOperationException: Unable to resolve service for type 'System.Net.Http.HttpClient' while attempting to activate 'WebScreen.Gate.Services.IPStackService'. Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, bool throwIfCallSiteNotFound)

如何为 HttpClient 正确设置类型化客户端?

最佳答案

IPStackService 的激活器(代码反射)找不到 HttpClient在 DI 集合中,这就是你得到异常的原因(特别是对于 services.AddTransient<IIPStackService, IPStackService>() )。

顺便说一句,你添加了服务IPStackService在您的 DI 集合中两次:

  1. services.AddHttpClient<IPStackService>(...); .
  2. services.AddTransient<IIPStackService, IPStackService>() ;

你只需要一个,因为你使用的是类型化客户端,你可以通过删除第二个并保留第一个来解决你的问题,并通过将契约(Contract)添加到实现中来稍微改变第一个,如下所示:

services.AddHttpClient<IIPStackService, IPStackService>(c =>
{
     c.BaseAddress = new Uri(Configuration["IPStackURL"]);
});

AddHttpClient将负责绑定(bind) HttpClient为您服务。


如果您想使用 services.AddTransient<IIPStackService, IPStackService>();而不是 services.AddHttpClient , 然后你需要添加 HttpClient作为您的 DI 集合:

services.AddTransient<HttpClient>();

关于c# - ASP.NET Core 类型化客户端中的 IHttpClientFactory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56091875/

相关文章:

c# - 如何从 json 数组创建列表集合?

visual-studio - 启动多个 asp .NET 核心项目时如何更改默认调试配置文件?

asp.net-mvc-3 - 用作 Action 方法参数的 View Model 实例的构造函数注入(inject)

java - 运行具有 Spring 依赖项的 Maven 项目时出现 ClassNotFoundException

c# - 安全使用 'HttpContext.Current.Cache'

c# - asp.net MSDeployEnableWebConfigEncryptRule 无法加密 web.config

c# - 按钮单击事件未从自定义 DataGridViewCell 触发

c# - 读取 .NET Core 测试项目中的 appsettings json 值

asp.net-core - 忽略 Swagger 中的 3rd 方 Controller 操作

c# - 针对每个 Web 请求和生命周期范围的 SimpleInjector 混合生活方式