简体   繁体   English

无法解析“System.Net.Http.HttpClient”类型的服务

[英]Unable to resolve service for type 'System.Net.Http.HttpClient'

I created a ViewComponent class which call a REST API using the HttpClient , this is the code:我创建了一个ViewComponent类,它使用HttpClient调用REST API ,这是代码:

public class ProductsViewComponent : ViewComponent
{
    private readonly HttpClient _client;

    public ProductsViewComponent(HttpClient client)
    {
        _client = client ?? throw new ArgumentNullException(nameof(client));
    }

    public async Task<IViewComponentResult> InvokeAsync(string date)
    {
        using(var response = await _client.GetAsync($"/product/get_products/{date}"))
        {
            response.EnsureSuccessStatusCode();
            var products = await response.Content.ReadAsAsync<List<Products>>();
            return View(products);
        }
    }
}

I get this error:我收到此错误:

InvalidOperationException: Unable to resolve service for type 'System.Net.Http.HttpClient' while attempting to activate MyApp.ViewComponents.ProductsViewComponent' InvalidOperationException:尝试激活 MyApp.ViewComponents.ProductsViewComponent 时无法解析类型“System.Net.Http.HttpClient”的服务

I injected the HttpClient in the ConfigureService method available in Startup in this way:我以这种方式在Startup中可用的ConfigureService方法中注入了HttpClient

 services.AddHttpClient<FixturesViewComponent>(options =>
 {
    options.BaseAddress = new Uri("http://80.350.485.118/api/v2");
 });

UPDATE:更新:

I registered the ProductsViewComponent too, same error.我也注册了ProductsViewComponent ,同样的错误。

I had a similar problem - the problem was in double registration:我有一个类似的问题 - 问题是双重注册:

services.AddHttpClient<Service>();
services.AddSingleton<Service>();  // fixed by removing this line

TLDR; TLDR; ViewComponent s do not support typed clients out of the box. ViewComponent不支持开箱即用的类型化客户端 To resolve this, add a call to AddViewComponentsAsServices() onto the end of the call to services.AddMvc(...) .要解决此问题,请在对services.AddMvc(...)的调用末尾添加对AddViewComponentsAsServices()的调用。


After a pretty long chat that ran off the back of being able to reproduce your issue, we determined initially that the problem being observed is specific to ViewComponent s.经过一段很长的聊天,因为能够重现您的问题,我们最初确定所观察到的问题是特定于ViewComponent的。 Even with a call to IServiceCollection.AddHttpClient<SomeViewComponent>() , passing an instance of HttpClient into SomeViewComponent s constructor just refused to work.即使调用IServiceCollection.AddHttpClient<SomeViewComponent>() ,将HttpClient的实例传递给SomeViewComponent的构造函数也只是拒绝工作。

However, sitting a new class ( SomeService ) between SomeComponent and HttpClient works as expected.但是,SomeComponentHttpClient之间SomeComponent一个新类 ( SomeService ) 可以按预期工作。 This is what the docs refer to as a typed client .这就是文档所说的类型化客户端 The code looks a bit like this:代码看起来有点像这样:

// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpClient<SomeService>();
    // ...
}

// SomeService.cs
public class SomeService
{
    public SomeService(HttpClient httpClient)
    {
        // ...
    }
}

// SomeViewComponent.cs
public class SomeViewComponent
{
    public SomeViewComponent(SomeService someService)
    {
        // ...
    }
}

As I've already stated, this approach works - the ASP.NET Core DI system is very happy to create the instance of SomeService and its typed HttpClient instance.正如我已经说过的,这种方法有效 - ASP.NET Core DI 系统非常乐意创建SomeService的实例及其类型化的HttpClient实例。

To restate the original problem, take the following example code:要重述原始问题,请使用以下示例代码:

public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpClient<SomeViewComponent>();
    // ...
}

public class SomeViewComponent
{
    public SomeViewComponent(HttpClient httpClient)
    {
        // ...
    }
}

In this case, the ASP.NET Core DI system refuses to create an instance of SomeViewComponent due to not being able to resolve HttpClient .在这种情况下,由于无法解析HttpClient ,ASP.NET Core DI 系统拒绝创建SomeViewComponent的实例。 It turns out that this is not specific just to ViewComponent s: it also applies to Controller s and TagHelper s (thanks to Chris Pratt for confirming for TagHelper s).事实证明,这不仅仅适用ViewComponent s:它也适用于Controller s 和TagHelper s(感谢 Chris Pratt 确认TagHelper s)。

Interestingly, the following also works:有趣的是,以下也有效:

public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpClient<SomeViewComponent>();
    // ...
}

public class SomeViewComponent
{
    public SomeViewComponent(IHttpClientFactory httpClientFactory)
    {
        var httpClient = httpClientFactory.CreateClient("SomeViewComponent")
        // ...
    }
}

In this example, we're taking advantage of the fact that the call to AddHttpClient<SomeViewComponent> registered a named client for us.在此示例中,我们利用了对AddHttpClient<SomeViewComponent>的调用为我们注册了一个命名客户端的事实。

In order to be able to inject HttpClient directly into a ViewComponent , we can add a call to AddViewComponentsAsServices when we register MVC with DI:为了能够将HttpClient直接注入到ViewComponent ,我们可以在向 DI 注册 MVC 时添加对AddViewComponentsAsServices的调用:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(...)
        .AddViewComponentsAsServices();
    // ...
}

AddControllersAsServices and AddTagHelpersAsServices can also be called to add the same support for Controller s and TagHelpers respectively. AddControllersAsServicesAddTagHelpersAsServices也可称为添加了同样的支持Controller S和TagHelpers分别。

If we look at the docs more closely, it's clear that none of the examples there inject a HttpClient into Controller s et al - there's simply no mention of this approach at all.如果我们更仔细地查看文档,很明显那里的示例都没有将HttpClient注入Controller等 - 根本没有提到这种方法。

Unfortunately, I don't know enough about the ASP.NET Core DI system in order to be able to explain exactly why this works the way it does: The information I've provided above simply explains the what along with a solution.不幸的是,我不知道有足够的了解ASP.NET的核心DI系统,以便能够准确解释为什么这个工作方式是这样:我上面提供的信息只是解释了什么一起的解决方案。 Chris Pratt has opened an issue in Github for the docs to be updated to expand upon this. Chris Pratt 已在 Github 中打开了一个问题,以便更新文档以对此进行扩展。

I was getting a similar error in my Azure Function Version 2. As per this document , we should be able to add the IHttpClientFactory as a dependency.我在Azure Function版本 2 中遇到了类似的错误。根据本文档,我们应该能够将IHttpClientFactory添加为依赖项。 After adding this DI in my Azure Function, I was getting the error mentioned below.在我的 Azure 函数中添加这个DI后,我收到了下面提到的错误。

Microsoft.Extensions.DependencyInjection.Abstractions: Unable to resolve service for type 'System.Net.Http.IHttpClientFactory' while attempting to activate 'OServiceBus.Adapter.FetchDataFromSubscription1' Microsoft.Extensions.DependencyInjection.Abstractions:尝试激活“OServiceBus.Adapter.FetchDataFromSubscription1”时无法解析“System.Net.Http.IHttpClientFactory”类型的服务

The issue was that I had not override the Configure function to add the HttpClient as a registered dependency.问题是我没有覆盖 Configure 函数来添加HttpClient作为注册的依赖项。 So I just created a class called Statup in the root directory of my Azure Function as follows.所以我只是在我的 Azure Function 的根目录中创建了一个名为Statup的类,如下所示。

using Microsoft.Azure.Functions.Extensions.DependencyInjection;使用 Microsoft.Azure.Functions.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;使用 Microsoft.Extensions.DependencyInjection;

[assembly: FunctionsStartup(typeof(ServiceBus.Adapter.Startup))]
namespace ServiceBus.Adapter {
    public class Startup: FunctionsStartup {
        public override void Configure(IFunctionsHostBuilder builder) {
            builder.Services.AddHttpClient();
        }
    }
}

After adding this, my function started working properly.添加后,我的功能开始正常工作。 Hope it helps.希望能帮助到你。

It seems that you've got two view components mixed up.您似乎混淆了两个视图组件。 You're registering the FixturesViewComponent as a "named HTTP client" yet you attempt to inject an HttpClient instance in the ProductsViewComponent .您将FixturesViewComponent注册为“命名的 HTTP 客户端”,但您尝试在ProductsViewComponent注入一个HttpClient实例。

Changing the HttpClient registration to ProductsViewComponent should help:将 HttpClient 注册更改为ProductsViewComponent应该会有所帮助:

services.AddHttpClient<ProductsViewComponent>(options =>
{
   options.BaseAddress = new Uri("http://80.350.485.118/api/v2");
});

I had a similar error message trying to inject a wrapper for an external REST service to my controller as an interface.我有一条类似的错误消息,试图将外部 REST 服务的包装器作为接口注入到我的控制器中。 I needed to change the following in ConfigureServices:我需要在 ConfigureServices 中更改以下内容:

services.AddHttpClient<IMyServiceWrapper>("MyServiceWrapper", client =>
{
   client.BaseAddress = new Uri("http://some_service/api");
}

to

services.AddHttpClient<IMyServiceWrapper, MyServiceWrapper>("MyServiceWrapper", client =>
{
   client.BaseAddress = new Uri("http://some_service/api");
}

in order to be able to use the interface in the constructor of my controller:为了能够在我的控制器的构造函数中使用接口:

public MyController(IMyServiceWrapper myService)
{
  _myService = myService;
}

Useful for testing myController using a mock service.用于使用模拟服务测试 myController。

Maybe it will help, but in my situation this worked:也许它会有所帮助,但在我的情况下这是有效的:

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<IMyService,MyService>(); // my usual DI injection of a service that can be mocked
    services.AddHttpClient<IMyService,MyService>(client => {
        client.BaseAddress = new Uri("https://myservice.com/api");
    }); // notice that I use IMyService for the reference of the registration AND implementation to where it will be injected.
}

public class MyService
{
    public MyService(HttpClient client)
    {
        // client.BaseAddress is properly set here
    }
}

public class MyController : Controller
{
    public MyController(IMyService service) // used by the interface
    {}
}

I've tried services.AddHttpClient<IMyService>() as well, which would not resolve due to lack of it's constructor.我也试过services.AddHttpClient<IMyService>() ,由于缺少它的构造函数而无法解决。 Also tried services.AddHttpClient<MyService>() as above, but it would not resolve the configured instance, as described above.还尝试了services.AddHttpClient<MyService>()如上所述,但它不会解析配置的实例,如上所述。

So the important part is that class that is used to reference the resolved type needs to be used.所以重要的部分是需要使用用于引用解析类型的类。 So this also works:所以这也有效:

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<MyService>(); // registering the type itself, not via interface
    services.AddHttpClient<MyService>(client => {
        client.BaseAddress = new Uri("https://myservice.com/api");
    }); // it's ok here, since it will be resolved by it's own type name
}

public class MyService
{
    public MyService(HttpClient client)
    {
        // client.BaseAddress is properly set here
    }
}

public class MyController : Controller
{
    public MyController(MyService service) // used by the type directly
    {}
}

It kind of makes sense, but documentation and examples could be better.这有点道理,但文档和示例可能会更好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法使用DI解析类型为&#39;System.Net.Http.HttpClient&#39;的服务 - Unable to resolve service for type 'System.Net.Http.HttpClient' using DI 尝试激活时无法解析类型“System.Net.Http.HttpClient”的服务 - Unable to resolve service for type 'System.Net.Http.HttpClient' while attempting to activate System.Net.Http.HttpClient如何选择身份验证类型? - How does the System.Net.Http.HttpClient select authentication type? System.Net.Http.HttpClient缓存 - System.Net.Http.HttpClient cache System.Net.Http.HttpClient 缓存行为 - System.Net.Http.HttpClient caching behavior 自动重试System.Net.Http.HttpClient - Automatic retry for the System.Net.Http.HttpClient Autofac 和 IHttpClientFactory:无法解析参数“System.Net.Http.HttpClient httpClient” - Autofac and IHttpClientFactory: Cannot resolve parameter 'System.Net.Http.HttpClient httpClient' 无法使用System.Net.Http.HttpClient从REST Web服务获得有效响应 - Can't get a valid response from a REST web service using System.Net.Http.HttpClient 使用 System.Net.Http.HttpClient 的并行 HTTP 请求 - Parallel HTTP requests using System.Net.Http.HttpClient 提供带有System.Net.Http.HttpClient和MVC的AntiForgery令牌 - Provide AntiForgery Token with System.Net.Http.HttpClient and MVC
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM