在ASP.NET vNext中访问config.json
文件(或存储其他配置的地方)的正确/推荐方法是什么?
在Startup
类中,我设置了如下配置:
public class Startup
{
public IConfiguration Configuration { get; set; }
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
{
var configurationBuilder = new ConfigurationBuilder(appEnv.ApplicationBasePath)
.AddJsonFile("config.json")
.AddEnvironmentVariables();
Configuration = configurationBuilder.Build();
}
但是如果我需要在别处访问连接字符串,我该怎么做?例如,在EF上下文的OnConfiguring
中,如何获取连接字符串:
protected override void OnConfiguring(EntityOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer( ??? );
我读过你可以用这个:
var config = Startup.Configuration
?? new Configuration()
.AddJsonFile("config.json")
.AddEnvironmentVariables();
但是(a)启动不是静态的,(b)你肯定不希望每次需要时重建配置设置 - 这是在任何地方重复使用的代码。
我还读过您应该使用Dependency Injection,但该链接并未完全告诉您如何操作。如果我的DbContext构造函数有一个注入参数,那么如何将它注入无参数的BaseApiController?
这看起来像是一个常见/简单的要求:在Startup中配置之后,如何在其他地方访问该配置?这应该在各地的文档/示例中。
答案 0 :(得分:1)
以下是我所做的工作:
public class Startup
{
public IConfiguration Configuration { get; set; }
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
{
// create & store the configuration once
var configurationBuilder = new ConfigurationBuilder(appEnv.ApplicationBasePath)
.AddJsonFile("config.json")
.AddEnvironmentVariables();
Configuration = configurationBuilder.Build();
}
public void ConfigureServices(IServiceCollection services)
{
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<Context>(options => options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
services.AddIdentity<User, IdentityRole>()
.AddEntityFrameworkStores<Context>()
.AddDefaultTokenProviders();
services.AddMvc();
// adding/registering the dbContext for dependency injection as a singleton
services.AddSingleton(s => new Context(Configuration));
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseIdentity();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action}/{id?}",
defaults: new { controller = "Home", action = "Index" });
});
}
}
public sealed class Context : IdentityDbContext<IdentityUser>
{
private readonly IConfiguration _config;
public DbSet<Client> Clients { get; set; }
public Context(IConfiguration config)
{
// store the injected config
_config = config;
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ForSqlServer().UseIdentity();
base.OnModelCreating(modelBuilder);
}
protected override void OnConfiguring(EntityOptionsBuilder optionsBuilder)
{
// use the injected config
optionsBuilder.UseSqlServer(_config.Get("Data:DefaultConnection:ConnectionString"));
base.OnConfiguring(optionsBuilder);
}
}
[Route("api/[controller]")]
public class TestController : BaseController
{
private readonly Context _context;
// have the context injected
public TestController(Context context)
{
_context = context;
}
[HttpGet]
public ActionResult Get()
{
return new ObjectResult(_context.Clients.ToList());
}
}
答案 1 :(得分:1)
首先,您应该避免将数据库上下文注册为单例。传递原始IConfiguration
界面也不是一个好习惯。
可以创建一个POCO选项类:
public class DbOptions
{
public string ConnectionString { get; set }
}
使用config.json中的部分填充ConfigureServices
方法:
services.Configure<DbOptions>(Configuration.GetConfigurationSection("Data:DefaultConnection"));
然后你可以把它注入你的DbContext
(以及控制器等):
public sealed class Context : IdentityDbContext<IdentityUser>
{
private readonly DbOptions _options;
public DbSet<Client> Clients { get; set; }
public Context(IOptions<DbOptions> optionsAccessor)
{
// store the injected options
_options = optionsAccessor.Options;
}
// other code..
}