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)
Dependency Injection is the design pattern that helps us to create an application which loosely coupled. This means that objects should only have those dependencies that are required to complete tasks.
ASP.NET Core supports dependency injection into views. This can be useful for view-specific services, such as localization or data required only for populating view elements. Most of the data views display should be passed in from the controller. View or download sample code (how to download)
ASP.NET Core supports the dependency injection (DI) software design pattern, which is a technique for achieving Inversion of Control (IoC) between classes and their dependencies. For more information specific to dependency injection within MVC controllers, see Dependency injection into controllers in ASP.NET Core.
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 } }
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With