ASP.Net Core MVC Dependency Injection not working

南楼画角 提交于 2019-12-30 00:28:14

问题


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

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

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:

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)


回答1:


Try injecting it as an IConfigurationRoot instead of 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 Configuration property 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:

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:

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

You can grab these configurations with the IOptions interface:

public HomeController(IOptions<AppSettings> appSettings)



回答2:


In Core 2.0 it's recommended to use IConfiguration instead of 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




回答3:


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



来源:https://stackoverflow.com/questions/36801831/asp-net-core-mvc-dependency-injection-not-working

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!