Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ASP.NET核心类型客户端中的IHttpClientFactory_C#_Asp.net Core_Dependency Injection_Dotnet Httpclient_Asp.net Core 2.1 - Fatal编程技术网

C# ASP.NET核心类型客户端中的IHttpClientFactory

C# ASP.NET核心类型客户端中的IHttpClientFactory,c#,asp.net-core,dependency-injection,dotnet-httpclient,asp.net-core-2.1,C#,Asp.net Core,Dependency Injection,Dotnet Httpclient,Asp.net Core 2.1,当我尝试为HttpClient使用类型化客户端时,我收到一个错误,如下所述: 以下是我的设置: Startup.cs: public void ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); services.AddDefaultAWSOptions(Configuratio

当我尝试为HttpClient使用类型化客户端时,我收到一个错误,如下所述:

以下是我的设置:

Startup.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>();
}
控制器:

[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;
    }
}
收到错误:

处理请求时发生未处理的异常。 InvalidOperationException:无法解析类型的服务 尝试激活时出现“System.Net.Http.HttpClient” “WebScreen.Gate.Services.IPStackService”。 Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSitesType serviceType,Type implementationType,CallSiteChain CallSiteChain, ParameterInfo[]参数,bool throwIfCallSiteNotFound

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

IPStackService代码反射的Activator在DI集合中找不到HttpClient,这就是为什么会出现专门针对services.AddTransient的异常

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

服务。AddHttpClient。。。;。 服务.AddTransient; 您只需要一个,因为您使用的是类型化客户端,所以您可以通过删除第二个并保留第一个来解决问题,并通过将契约添加到实现中来稍微修改第一个,如下所示:

services.AddHttpClient<IIPStackService, IPStackService>(c =>
{
     c.BaseAddress = new Uri(Configuration["IPStackURL"]);
});
IPStackService代码反射的Activator在DI集合中找不到HttpClient,这就是为什么会出现专门针对services.AddTransient的异常

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

服务。AddHttpClient。。。;。 服务.AddTransient; 您只需要一个,因为您使用的是类型化客户端,所以您可以通过删除第二个并保留第一个来解决问题,并通过将契约添加到实现中来稍微修改第一个,如下所示:

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

恕我直言,我认为使用services.AddTransient;添加HttpClient不是一个好主意;。这将为每个请求创建HttpClient,如果HttpClient实例未正确处理,则可能导致套接字打开。然而,AddHttpClient使用IHttpClientFactory并将在幕后管理HttpMessageHandler的生命周期。我完全同意你所说的。我刚才提到它是一种解决方案,以防他想采用第二种方法。我认为使用services.AddTransient;添加HttpClient不是一个好主意;。这将为每个请求创建HttpClient,如果HttpClient实例未正确处理,则可能导致套接字打开。然而,AddHttpClient使用IHttpClientFactory并将在幕后管理HttpMessageHandler的生命周期。我完全同意你所说的。我刚才提到这是一个解决方案,以防他想采用第二种方法。