asp.net-mvc ASP.Net Core MVC 依赖注入不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36801831/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-07 23:32:30  来源:igfitidea点击:

ASP.Net Core MVC Dependency Injection not working

asp.net-mvcdependency-injectionasp.net-core

提问by JamTay317

I am trying to inject a interface into to my HomeController and I am getting this error:

我正在尝试将接口注入到我的 HomeController 中,但出现此错误:

InvalidOperationException: Unable to resolve service for type 'Microsoft.Extensions.Configuration.IConfiguration' while attempting to activate

InvalidOperationException:尝试激活时无法解析“Microsoft.Extensions.Configuration.IConfiguration”类型的服务

My Startup class is as follows:

我的启动类如下:

public Startup(IApplicationEnvironment appEnv)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(appEnv.ApplicationBasePath)
        .AddEnvironmentVariables()
        .AddJsonFile("appsettings.json");
    Configuration = builder.Build();
}

public IConfigurationRoot Configuration { get; set; }

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddApplicationInsightsTelemetry(Configuration);

    services.AddEntityFramework()
        .AddSqlServer()
        .AddDbContext<ApplicationDbContext>(options => options
            .UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));

    services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    services.AddMvc();
    services.AddSingleton(provider => Configuration);

    // Add application services.
    services.AddTransient<IEmailSender, AuthMessageSender>();
    services.AddTransient<ISmsSender, AuthMessageSender>();
}

public void Configure(
    IApplicationBuilder app, 
    IHostingEnvironment env, 
    ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    app.UseApplicationInsightsRequestTelemetry();

    if (env.IsDevelopment())
    {
        app.UseBrowserLink();
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");

        try
        {
            using (var serviceScope = app.ApplicationServices
                .GetRequiredService<IServiceScopeFactory>()
                .CreateScope())
            {
                serviceScope.ServiceProvider
                        .GetService<ApplicationDbContext>()
                        .Database.Migrate();
            }
        }
        catch { }
    }

    app.UseIISPlatformHandler(options => options.AuthenticationDescriptions.Clear());

    app.UseApplicationInsightsExceptionTelemetry();
    app.UseStaticFiles();
    app.UseIdentity();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });

    app.Run((async (context) =>
    {
        await context.Response.WriteAsync("Error");
    }));
}

and my HomeController constructor is:

我的 HomeController 构造函数是:

public HomeController(IConfiguration configuration, IEmailSender mailService)
{
    _mailService = mailService;
    _to = configuration["emailAddress.Support"];
}

Please tell me where I am mistaken.

请告诉我我错在哪里。

Microsoft.Extensions.DependencyInjection.ServiceLookup.Service.PopulateCallSites(ServiceProvider provider, ISet`1 callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)

Microsoft.Extensions.DependencyInjection.ServiceLookup.Service.PopulateCallSites(ServiceProvider provider, ISet`1 callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)

回答by Will Ray

Try injecting it as an IConfigurationRootinstead of IConfiguration:

尝试将其注入IConfigurationRoot而不是IConfiguration

 public HomeController(IConfigurationRoot configuration
    , IEmailSender mailService)
{
    _mailService = mailService;
    _to = configuration["emailAddress.Support"];
}

In this case, the line

在这种情况下,该行

services.AddSingleton(provider => Configuration);

is equivalent to

相当于

services.AddSingleton<IConfigurationRoot>(provider => Configuration);

because the Configurationproperty on the class is declared as such, and injection will be done by matching whatever type it was registered as. We can replicate this pretty easily, which might make it clearer:

因为Configuration类上的属性是这样声明的,注入将通过匹配它注册为的任何类型来完成。我们可以很容易地复制这个,这可能会更清楚:

public interface IParent { }

public interface IChild : IParent { }

public class ConfigurationTester : IChild { }
public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddMvc();

    IChild example = new ConfigurationTester();
    services.AddSingleton(provider => example);
}
public class HomeController : Controller
{
    public HomeController(IParent configuration)
    {
        // this will blow up
    }
}

However

然而

As stephen.vakil mentioned in the comments, it would be better to load your configuration file into a class, and then inject that class into controllers as needed. That would look something like this:

正如评论中提到的 stephen.vakil ,最好将您的配置文件加载到一个类中,然后根据需要将该类注入到控制器中。这看起来像这样:

services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));

You can grab these configurations with the IOptionsinterface:

您可以通过IOptions界面获取这些配置:

public HomeController(IOptions<AppSettings> appSettings)

回答by Michael Freidgeim

In Core 2.0 it's recommended to use IConfiguration instead of IConfigurationRoot

在 Core 2.0 中,建议使用 IConfiguration 而不是 IConfigurationRoot

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}

public IConfiguration Configuration { get; }

from https://docs.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/#add-configuration-providers

来自https://docs.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/#add-configuration-providers

回答by Christian Esqueda

When moving a project from .Net Core 1.x to 2.0, change all IConfigurationRootto IConfiguration

将项目从 .Net Core 1.x 移动到 2.0 时,将 all 更改IConfigurationRootIConfiguration