ASP.NET Core 1.0 基础之配置
2016-01-25 19:12
941 查看
来源https://docs.asp.net/en/latest/fundamentals/configuration.html
ASP.NET Core 1.0支持不同的配置选项。应用配置数据可以是来自Json,XML,INI等格式,这些格式都是内建支持。当然配置数据也可以来自环境变量。你也可以写自己的环境provider。
你可以从Github下载样例代码。
为了处理配置问题,推荐的做法是在Startup类中,实例化一个Configuration对象,然后使用options pattern来接入不同的配置。
简单来说,Configuration是一系列配置provider的集合,提供读取和写入键对值的功能。为了Configuration能正常工作,至少要配置一个provider。下例展示了怎样测试作为键对值存储的Configuration。
Note:你必须设置至少一个provider
通常情况下,配置数据是分层结构存储的,尤其使用外部文件时,如Json,XML,INI等。在这种情况下,配置数据可以通过分隔符:来获取。考虑如下配置文件
应用使用配置文件来配置连接字符串,获取该值可以使用这样的键Data:DefaultConnection:ConnectionString。
使用options pattern可以解耦应用所需的配置和获取指定配置的机制。为了使用options pattern,你需要创建自己的设置类(或许是几个不同的类,对应几个不同的内聚的设置组),这样你可以使用options 服务将他们注入你的应用。然后你可以使用configuration或者任何你选择的机制来指定settings。
Note: 你可以将Configuration实例作为服务存储起来,但是这会不必要地将你的应用和单一配置系统以及特定的配置keys耦合起来。你应该使用Options pattern来避免该问题。
通过扩展方法,可以实现对其他配置文件provider的支持。这些方法由ConfigurationBuilder单独调用或者作为fluent API调用,如下
configuration providers的顺序是很重要的,因为这决定了如果配置在多个位置的话,哪个配置将会被应用。如上例,如果同样的值存在appsettings.json和环境变量中,环境变量中的配置将会被应用。如果配置存在多个位置,最后一个provider指定的值将会覆盖之前的值。ASP.NET团队推荐将环境变量的配置放在最后,这样本地环境变量将会覆盖任何被部署的配置文件。
Note: 在shell中通过环境变量覆盖嵌套的值,并不支持“:”,而是使用“__”(double undercore)。
使用基于环境的配置文件是很有用的,如下
IHostingEnvironment 服务用来获取当前环境,如果在Development环境,第6行代码将会查找appsettings.Development.json文件,如果存在的话,并使用其中的配置项来重写其他的值,详见Working with Multiple Environments。
Warning:你绝对不应存储密码或其他敏感信息在provider代码中或者配置文件中。你也不应该在开发和测试环境中使用生产环境密码。事实上,这些信息应该在项目树之外指定,这样能避免偶然情况下将其提交到provider仓储中。详见Multiple Environments和管理Safe Storage of Application Secrets。
一种可以利用Configuration优先级顺序的方式是使用默认值,默认值可被覆盖。在如下控制台程序中,username的默认值是在MemoryConfigurationProvider中指定的,如果命令行参数中提供了username的值,那么该值会被重写。你可以查看多个Configuration provider在不同阶段时,程序的输出。
但程序运行时,除非命令行参数覆盖,程序将会输出默认值
如下一个简单的MyOptions的例子
通过IOptions服务可以将Options注入应用。例如,MVC controller利用IOptions来获取填充index视图所需的配置。
更多详见依赖注入。
为了启动IOpitons服务,你需要在Startup类中ConfigureServices中调用扩展方法AddOptions()。
Index视图显示如下
通过扩展方法Configure来配置选项。可以通过使用delegate或者绑定options到Configuration。
当绑定options到configuration时,配置类中的属性绑定的key具有property:subproperty:...的形式。例如,MyOptions.Option1所绑定key就是Option1,它是从appsettings.json的option1键中读取的。注意配置键是大小写不敏感的。
每次调用Configure都添加一个IConfigurations到服务容器中,然后有IOptions来将配置选项提供给应用或框架。如果你想使用别的方式直接配置选项(如从数据库读取设置),你可以直接使用ConfigureOptions的服务。
对于同样的配置选项,你可以使用多个IConfiguration服务,他们会按顺序起作用。在上例中Option1和Option2值都在appsettings.json中指定,但是option1的值会被configuration delegate所覆盖。
首先我们定义ConfigurationValue,来存储数据到数据库中。
我们还需要一个ConfigurationContext来使用EF存储或获取配置选项值。
然后创建configuration provider。配置数据通过重写Load方法来载入,它从数据库中读取所有的配置数据。为了演示的目的,如果数据库没有存在和populate,configuration provider会首先创建并初始化数据库。
同时,我们还需要添加AddEntityFramework扩展方法来添加configuration provider
在下例中,你可以看到如何在应用中使用自定义configuration provider。创建ConfigurationBuilder 来setup你的configuration provders。添加EntityFrameworkConfigurationProvider来指定data provider和连接字符串。怎样配置连接字符串呢?当然是使用配置,添加appsettings.json文件作为configuration provider来启动EntityFrameworkConfigurationProvider。通过复用ConfigurationBuilder,数据中任何配置数据都能够重写appsettings.json中数据。
运行程序,可以看到如下结果
ASP.NET Core 1.0支持不同的配置选项。应用配置数据可以是来自Json,XML,INI等格式,这些格式都是内建支持。当然配置数据也可以来自环境变量。你也可以写自己的环境provider。
你可以从Github下载样例代码。
获取和设置环境配置
ASP.NET Core 1.0的环境系统是经过重新设计的,不像之前的是依赖于System.Configuration和类似web.config之类的xml文件的。新的配置模型中,配置可以从不同的provider中获取,并且这些设置是支持streamlined键值对获取的。使用新的options pattern,应用和框架可以获取配置。为了处理配置问题,推荐的做法是在Startup类中,实例化一个Configuration对象,然后使用options pattern来接入不同的配置。
简单来说,Configuration是一系列配置provider的集合,提供读取和写入键对值的功能。为了Configuration能正常工作,至少要配置一个provider。下例展示了怎样测试作为键对值存储的Configuration。
// assumes using Microsoft.Framework.ConfigurationModel is specified var builder = new ConfigurationBuilder(); builder.Add(new MemoryConfigurationProvider()); var config = builder.Build(); config.Set("somekey", "somevalue"); // do some other work string setting2 = config["somekey"]; // also returns "somevalue"
Note:你必须设置至少一个provider
通常情况下,配置数据是分层结构存储的,尤其使用外部文件时,如Json,XML,INI等。在这种情况下,配置数据可以通过分隔符:来获取。考虑如下配置文件
{ "Data": { "DefaultConnection": { "ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=aspnet5-WebApplication1-8479b9ce-7b8f-4402-9616-0843bc642f09;Trusted_Connection=True;MultipleActiveResultSets=true" } }, "Logging": { "IncludeScopes": false, "LogLevel": { "Default": "Verbose", "System": "Information", "Microsoft": "Information" } } }
应用使用配置文件来配置连接字符串,获取该值可以使用这样的键Data:DefaultConnection:ConnectionString。
使用options pattern可以解耦应用所需的配置和获取指定配置的机制。为了使用options pattern,你需要创建自己的设置类(或许是几个不同的类,对应几个不同的内聚的设置组),这样你可以使用options 服务将他们注入你的应用。然后你可以使用configuration或者任何你选择的机制来指定settings。
Note: 你可以将Configuration实例作为服务存储起来,但是这会不必要地将你的应用和单一配置系统以及特定的配置keys耦合起来。你应该使用Options pattern来避免该问题。
使用内建的provider
配置框架有内置的对JSON,XML和INI配置文件的支持,同样的支持内存中的配置(直接在代码中设置值),以及从环境配置和命令行参数中取得配置。开发者并不局限于一种provider。事实上,若干个provider可以一起使用,这样的话默认的配置会被其他provider提供的配置所覆盖(如果存在的话)。通过扩展方法,可以实现对其他配置文件provider的支持。这些方法由ConfigurationBuilder单独调用或者作为fluent API调用,如下
var config = builder.Build(); builder.AddEntityFramework(options => options.UseSqlServer(config["Data:DefaultConnection:ConnectionString"])); config = builder.Build();
configuration providers的顺序是很重要的,因为这决定了如果配置在多个位置的话,哪个配置将会被应用。如上例,如果同样的值存在appsettings.json和环境变量中,环境变量中的配置将会被应用。如果配置存在多个位置,最后一个provider指定的值将会覆盖之前的值。ASP.NET团队推荐将环境变量的配置放在最后,这样本地环境变量将会覆盖任何被部署的配置文件。
Note: 在shell中通过环境变量覆盖嵌套的值,并不支持“:”,而是使用“__”(double undercore)。
使用基于环境的配置文件是很有用的,如下
public Startup(IHostingEnvironment env) { // Set up configuration providers. var builder = new ConfigurationBuilder() .AddJsonFile("appsettings.json") .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); if (env.IsDevelopment()) { // For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709 builder.AddUserSecrets(); } builder.AddEnvironmentVariables(); Configuration = builder.Build(); }
IHostingEnvironment 服务用来获取当前环境,如果在Development环境,第6行代码将会查找appsettings.Development.json文件,如果存在的话,并使用其中的配置项来重写其他的值,详见Working with Multiple Environments。
Warning:你绝对不应存储密码或其他敏感信息在provider代码中或者配置文件中。你也不应该在开发和测试环境中使用生产环境密码。事实上,这些信息应该在项目树之外指定,这样能避免偶然情况下将其提交到provider仓储中。详见Multiple Environments和管理Safe Storage of Application Secrets。
一种可以利用Configuration优先级顺序的方式是使用默认值,默认值可被覆盖。在如下控制台程序中,username的默认值是在MemoryConfigurationProvider中指定的,如果命令行参数中提供了username的值,那么该值会被重写。你可以查看多个Configuration provider在不同阶段时,程序的输出。
using System; using System.Linq; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.Memory; namespace ConfigConsole { public class Program { public void Main(string[] args) { var builder = new ConfigurationBuilder(); Console.WriteLine("Initial Config Providers: " + builder.Providers.Count()); var defaultSettings = new MemoryConfigurationProvider(); defaultSettings.Set("username", "Guest"); builder.Add(defaultSettings); Console.WriteLine("Added Memory Provider. Providers: " + builder.Providers.Count()); builder.AddCommandLine(args); Console.WriteLine("Added Command Line Provider. Providers: " + builder.Providers.Count()); var config = builder.Build(); string username = config["username"]; Console.WriteLine($"Hello, {username}!"); } } }
但程序运行时,除非命令行参数覆盖,程序将会输出默认值
使用Options和配置对象
使用Options你可以轻易的将任何POCO类转换成设置类。推荐的做法是,在应用中对应某种feature,创建一个良好解耦的配置对象。遵循接口隔离原则(ISP)的同时也满足关注点分离(不同部分的配置是分开管理的,因此减少相互不利影响)。如下一个简单的MyOptions的例子
public class MyOptions { public string Option1 { get; set; } public int Option2 { get; set; } }
通过IOptions服务可以将Options注入应用。例如,MVC controller利用IOptions来获取填充index视图所需的配置。
public class HomeController : Controller { public HomeController(IOptions<MyOptions> optionsAccessor) { Options = optionsAccessor.Value; } MyOptions Options { get; } // GET: /<controller>/ public IActionResult Index() { return View(Options); } }
更多详见依赖注入。
为了启动IOpitons服务,你需要在Startup类中ConfigureServices中调用扩展方法AddOptions()。
public void ConfigureServices(IServiceCollection services) { // Setup options with DI services.AddOptions(); }
Index视图显示如下
通过扩展方法Configure来配置选项。可以通过使用delegate或者绑定options到Configuration。
public void ConfigureServices(IServiceCollection services) { // Setup options with DI services.AddOptions(); // Configure MyOptions using config services.Configure<MyOptions>(Configuration); // Configure MyOptions using code services.Configure<MyOptions>(myOptions => { myOptions.Option1 = "value1_from_action"; }); // Add framework services. services.AddMvc();
当绑定options到configuration时,配置类中的属性绑定的key具有property:subproperty:...的形式。例如,MyOptions.Option1所绑定key就是Option1,它是从appsettings.json的option1键中读取的。注意配置键是大小写不敏感的。
每次调用Configure都添加一个IConfigurations到服务容器中,然后有IOptions来将配置选项提供给应用或框架。如果你想使用别的方式直接配置选项(如从数据库读取设置),你可以直接使用ConfigureOptions的服务。
对于同样的配置选项,你可以使用多个IConfiguration服务,他们会按顺序起作用。在上例中Option1和Option2值都在appsettings.json中指定,但是option1的值会被configuration delegate所覆盖。
写自定义provider
除了使用内建的configuration provider,你也可以编写自己的。你只需要继承ConfigurationProvider类,然后populate the Data property with the settings from your configuration provider。例子:EF设置
你可能希望存储一些应用设置选项到数据库中,使用EF来获取它们。你可以有很多方式存储设置,在本例中,我们创建一个简单的configuration provider,来使用EF读取数据库中的name-value对。首先我们定义ConfigurationValue,来存储数据到数据库中。
public class ConfigurationValue { public string Id { get; set; } public string Value { get; set; } }
我们还需要一个ConfigurationContext来使用EF存储或获取配置选项值。
public class ConfigurationContext : DbContext { public ConfigurationContext(DbContextOptions options) : base(options) { } public DbSet<ConfigurationValue> Values { get; set; } }
然后创建configuration provider。配置数据通过重写Load方法来载入,它从数据库中读取所有的配置数据。为了演示的目的,如果数据库没有存在和populate,configuration provider会首先创建并初始化数据库。
public class EntityFrameworkConfigurationProvider : ConfigurationProvider { public EntityFrameworkConfigurationProvider(Action<DbContextOptionsBuilder> optionsAction) { OptionsAction = optionsAction; } Action<DbContextOptionsBuilder> OptionsAction { get; } public override void Load() { var builder = new DbContextOptionsBuilder<ConfigurationContext>(); OptionsAction(builder); using (var dbContext = new ConfigurationContext(builder.Options)) { dbContext.Database.EnsureCreated(); Data = !dbContext.Values.Any() ? CreateAndSaveDefaultValues(dbContext) : dbContext.Values.ToDictionary(c => c.Id, c => c.Value); } } private IDictionary<string, string> CreateAndSaveDefaultValues(ConfigurationContext dbContext) { var configValues = new Dictionary<string, string> { { "key1", "value_from_ef_1" }, { "key2", "value_from_ef_2" } }; dbContext.Values.AddRange(configValues .Select(kvp => new ConfigurationValue() { Id = kvp.Key, Value = kvp.Value }) .ToArray()); dbContext.SaveChanges(); return configValues; } }
同时,我们还需要添加AddEntityFramework扩展方法来添加configuration provider
public static class EntityFrameworkExtensions { public static IConfigurationBuilder AddEntityFramework(this IConfigurationBuilder builder, Action<DbContextOptionsBuilder> setup) { return builder.Add(new EntityFrameworkConfigurationProvider(setup)); } }
在下例中,你可以看到如何在应用中使用自定义configuration provider。创建ConfigurationBuilder 来setup你的configuration provders。添加EntityFrameworkConfigurationProvider来指定data provider和连接字符串。怎样配置连接字符串呢?当然是使用配置,添加appsettings.json文件作为configuration provider来启动EntityFrameworkConfigurationProvider。通过复用ConfigurationBuilder,数据中任何配置数据都能够重写appsettings.json中数据。
public class Program
{
public static void Main(string[] args)
{
var builder = new ConfigurationBuilder();
builder.AddJsonFile("appsettings.json");
builder.AddEnvironmentVariables();
var config = builder.Build(); builder.AddEntityFramework(options => options.UseSqlServer(config["Data:DefaultConnection:ConnectionString"])); config = builder.Build();
Console.WriteLine("key1={0}", config["key1"]);
Console.WriteLine("key2={0}", config["key2"]);
Console.WriteLine("key3={0}", config["key3"]);
}
}
运行程序,可以看到如下结果
总结
ASP.NET Core 1.0提供很大灵活性的配置模型,可以支持不同文件类型配置,以及命令行,内存和环境变量等配置。他可以与options无缝连接,所以你可以注入强类型的配置到应用或框架中。同时你也可以创建自己的configuration provider,来和内嵌的provider配合,或者取代它们。相关文章推荐
- Creating the Help Page in ASP.NET Web API
- Backup Raspbx system
- 1.casperjs的安装与环境配置
- ASP.NET网站如何实现不同域名解析不同的子目录
- asprintf
- Owin管道与asp.net管道模型
- Asp.Net前台调用后台变量的方法
- ASP与ASP.NET的区别与比较
- ASP.NET网站管理工具无法连接SQL&amp;n…
- Asp.net原理:Asp.net管道&nbsp;(…
- ASP.NET MVC4.0+EF+LINQ+bui+网站+角色权限管理系统(5)
- ASP.NET学习路线图(入门)
- Asp.Net 文件加解密
- Asp.Net 启用全局IE兼容模式
- 提高 ASP.NET Web 应用性能
- ASP
- 【转】 (C#)利用Aspose.Cells组件导入导出excel文件
- 详解 ASP.NET异步
- 提高 ASP.NET Web 应用性能的 24 种方法和技巧
- ASP.Net基础知识积累