ASP.Net Core MVC 依赖注入不起作用

Posted

技术标签:

【中文标题】ASP.Net Core MVC 依赖注入不起作用【英文标题】:ASP.Net Core MVC Dependency Injection not working 【发布时间】:2016-04-22 19:24:43 【问题描述】:

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

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

我的 Startup 类如下:

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");
    ));

而我的 HomeController 构造函数是:

public HomeController(IConfiguration configuration, IEmailSender mailService)

    _mailService = mailService;
    _to = configuration["emailAddress.Support"];

请告诉我我错在哪里。

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

【问题讨论】:

我建议您通过创建一个 POCO 来存储您想要传递的任何配置详细信息并将其注入,从而将您的 Configuration 与您的 Controller 隔离开来。 如果构造函数有对象作为参数,但服务配置为接口***.com/questions/40900414/…,也会发生类似的错误 【参考方案1】:

尝试将其注入为IConfigurationRoot 而不是IConfiguration

 public HomeController(IConfigurationRoot configuration
    , IEmailSender mailService)

    _mailService = mailService;
    _to = configuration["emailAddress.Support"];

在这种情况下,行

services.AddSingleton(provider => Configuration);

相当于

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

因为类上的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
    

然而

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

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

您可以通过IOptions 接口获取这些配置:

public HomeController(IOptions<AppSettings> appSettings)

【讨论】:

为什么?我没有在我的代码中这样做,它仍然可以正常工作。并且在文档中没有按此顺序完成:docs.asp.net/en/latest/fundamentals/dependency-injection.html @stephen.vakil 你是对的,我在那个细节上完全错了。感谢您的链接! Jam,我已经更新了我的答案。 就是这样!你能解释一下有什么区别吗? 将其作为IConfiguration 注入以获得更大的灵活性。【参考方案2】:

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

public Startup(IConfiguration configuration)

    Configuration = configuration;


public IConfiguration Configuration  get; 

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

【讨论】:

【参考方案3】:

将项目从 .Net Core 1.x 移动到 2.0 时,将所有 IConfigurationRoot 更改为 IConfiguration

【讨论】:

以上是关于ASP.Net Core MVC 依赖注入不起作用的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core MVC 之依赖注入 Controller

ASP.NET Core Web 应用程序系列- 使用ASP.NET Core内置的IoC容器DI进行批量依赖注入(MVC当中应用)

如何在 ASP.NET Core MVC 中使用依赖注入设计存储库模式?

ASP.NET Core Web 应用程序系列- 在ASP.NET Core中使用Autofac替换自带DI进行构造函数和属性的批量依赖注入(MVC当中应用)

ASP.NET Core Web 应用程序系列- 在ASP.NET Core中使用Autofac替换自带DI进行构造函数和属性的批量依赖注入(MVC当中应用)

ASP.NET CORE MVC 身份用户和角色不起作用