ASP.Net Core MVC Injection не работает
Я пытаюсь ввести интерфейс в свой HomeController, и я получаю эту ошибку.
InvalidOperationException: не удается разрешить службу для типа "Microsoft.Extensions.Configuration.IConfiguration" при попытке активировать
Мой начальный файл выглядит следующим образом
public Startup(IApplicationEnvironment appEnv)
{
var builder = new ConfigurationBuilder()
.SetBasePath(appEnv.ApplicationBasePath)
.AddEnvironmentVariables()
.AddJsonFile("appsettings.json");
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; set; }
// This method gets called by the runtime. Use this method to add services to the container.
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>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
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");
// For more details on creating database during deployment see http://go.microsoft.com/fwlink/?LinkID=615859
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();
// To configure external authentication please see http://go.microsoft.com/fwlink/?LinkID=532715
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
app.Run((async (context) =>
{
await context.Response.WriteAsync("Error");
}));
}
и конструктор моего домашнего контроллера:
public HomeController(IConfiguration configuration
, IEmailSender mailService)
{
_mailService = mailService;
_to = configuration["emailAddress.Support"];
}
скажите, пожалуйста, где я ошибаюсь.
Microsoft.Extensions.DependencyInjection.ServiceLookup.Service.PopulateCallSites(поставщик ServiceProvider, ISet`1 callSiteChain, ParameterInfo [], Boolean throwIfCallSiteNotFound)
Ответы
Ответ 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
}
}
Однако
Как указано в комментариях stephen.vakil, было бы лучше загрузить файл конфигурации в класс, а затем при необходимости добавить этот класс в контроллеры. Это будет выглядеть примерно так:
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
Вы можете захватить эти конфигурации с помощью интерфейса IOptions
:
public HomeController(IOptions<AppSettings> appSettings)
Ответ 2
В 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
Ответ 3
При перемещении проекта из .Net Core 1.x в 2.0 измените все IConfigurationRoot
на IConfiguration