关于c#:无法解析类型为’System.Net.Http.HttpClient’的服务

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

我创建了一个ViewComponent类,该类使用HttpClient调用REST API,这是代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class ProductsViewComponent : ViewComponent
{
    private readonly HttpClient _client;

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

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

我收到此错误:

InvalidOperationException: Unable to resolve service for type 'System.Net.Http.HttpClient' while attempting to activate MyApp.ViewComponents.ProductsViewComponent'

我以这种方式将HttpClient注入了Startup中可用的ConfigureService方法中:

1
2
3
4
 services.AddHttpClient;lt;FixturesViewComponent;gt;(options =;gt;
 {
    options.BaseAddress = new Uri("http://80.350.485.118/api/v2");
 });

更新:

我也注册了ProductsViewComponent,同样的错误。


我有一个类似的问题-问题出在双重注册中:

1
2
services.AddHttpClient;lt;Service;gt;();
services.AddSingleton;lt;Service;gt;();  // fixed by removing this line


TLDR;
ViewComponent不支持开箱即用的类型化客户端。要解决此问题,请将对AddViewComponentsAsServices()的调用添加到对services.AddMvc(...)的调用的末尾。

经过一段漫长的聊天,之后又无法重现您的问题,我们最初确定观察到的问题是特定于ViewComponent的。即使调用IServiceCollection.AddHttpClient(),将HttpClient的实例传递给SomeViewComponent的构造函数也只是拒绝工作。

但是,在SomeComponentHttpClient之间放置一个新类(SomeService)可以正常工作。这就是文档所称的类型化客户端。该代码看起来像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 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)
    {
        // ...
    }
}

正如我已经说过的,这种方法行之有效-ASP.NET Core DI系统非常高兴创建SomeService实例及其类型化的HttpClient实例。

要重述原始问题,请使用以下示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpClient<SomeViewComponent>();
    // ...
}

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

在这种情况下,ASP.NET Core DI系统由于无法解析HttpClient而拒绝创建SomeViewComponent实例。事实证明,这不仅限于ViewComponent:还适用于ControllerTagHelper(感谢Chris Pratt确认了TagHelper)。

有趣的是,以下内容也适用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpClient<SomeViewComponent>();
    // ...
}

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

在此示例中,我们利用了对AddHttpClient的调用为我们注册了命名客户端这一事实。

为了能够将HttpClient直接注入到ViewComponent中,我们可以在用DI注册MVC时向AddViewComponentsAsServices添加调用:

1
2
3
4
5
6
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(...)
        .AddViewComponentsAsServices();
    // ...
}

也可以调用AddControllersAsServicesAddTagHelpersAsServices来分别添加对ControllerTagHelpers的相同支持。

如果我们更仔细地研究文档,很明显那里没有示例将HttpClient注入Controller s等人中-根本没有提及这种方法。

不幸的是,我对ASP.NET Core DI系统了解不足,无法确切解释其工作原理:上面提供的信息仅说明了解决方案。克里斯·普拉特(Chris Pratt)在Github中打开了一个问题,要求对文档进行更新以扩展此范围。


我在Azure Function版本2中遇到了类似的错误。根据本文档,我们应该能够将IHttpClientFactory添加为依赖项。在我的Azure函数中添加此DI之后,我遇到了下面提到的错误。

Microsoft.Extensions.DependencyInjection.Abstractions: Unable to
resolve service for type 'System.Net.Http.IHttpClientFactory' while
attempting to activate
'OServiceBus.Adapter.FetchDataFromSubscription1'

问题是我没有重写Configure函数以将HttpClient添加为已注册的依赖项。因此,我仅在Azure函数的根目录中创建了一个名为Statup的类,如下所示。

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

1
2
3
4
5
6
7
8
[assembly: FunctionsStartup(typeof(ServiceBus.Adapter.Startup))]
namespace ServiceBus.Adapter {
    public class Startup: FunctionsStartup {
        public override void Configure(IFunctionsHostBuilder builder) {
            builder.Services.AddHttpClient();
        }
    }
}

添加后,我的功能开始正常工作。希望能帮助到你。


看来您将两个视图组件混在一起了。您正在将FixturesViewComponent注册为"命名的HTTP客户端",但尝试在ProductsViewComponent中注入HttpClient实例。

将HttpClient注册更改为ProductsViewComponent应该会有所帮助:

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

我有一个类似的错误消息,试图将外部REST服务的包装器作为接口注入控制器。我需要在ConfigureServices中更改以下内容:

1
2
3
4
services.AddHttpClient;lt;IMyServiceWrapper;gt;("MyServiceWrapper", client =;gt;
{
   client.BaseAddress = new Uri("http://some_service/api");
}

1
2
3
4
services.AddHttpClient;lt;IMyServiceWrapper, MyServiceWrapper;gt;("MyServiceWrapper", client =;gt;
{
   client.BaseAddress = new Uri("http://some_service/api");
}

为了能够在我的控制器的构造函数中使用该接口:

1
2
3
4
public MyController(IMyServiceWrapper myService)
{
  _myService = myService;
}

对于使用模拟服务测试myController很有用。