ASP.NET Core 中的配置是使用一个或多个配置提供程序执行的。 配置提供程序使用各种配置源从键值对读取配置数据:
-
设置文件,例如 appsettings.json
-
环境变量
-
Azure Key Vault
-
Azure 应用程序配置
-
命令行参数
-
已安装或已创建的自定义提供程序
-
目录文件
-
内存中的 .NET 对象
获取配置的键值可以使用Configuration["MyKey"],有多层次的键值的话可以用冒号分隔Configuration["MyKey:MyKeyCh"],获取的结果为字符串。
可以通过GetValue方法返回指定的数据类型,并设置默认值,如下代码99为默认值。
Configuration.GetValue<int>("NumberKey", 99)
可以使用GetSection方法返回指定键的子配置数据。
var config = Configuration.GetSection("MyKey"); //config["Key1"]; //config["Key2"];
GetSection永远不会返回null,如果键匹配不到,则会返回空IConfigurationSection,并且Value会为null。 我们可以用Exists方法来判断是存在该节点。
config.Exists() ? "存在" : "不存在"
通过GetChildren方法可以获取GetSection获取的节点的所有键值对。
var selection = Config.GetSection("section2"); if (!selection.Exists()) { throw new System.Exception("section2 does not exist."); } var children = selection.GetChildren(); foreach (var subSection in children) { int i = 0; var key1 = subSection.Key + ":key" + i++.ToString(); var key2 = subSection.Key + ":key" + i.ToString(); s += key1 + " value: " + selection[key1] + "\n"; s += key2 + " value: " + selection[key2] + "\n"; }
配置的键值有以下的要求:
键:
1.不区分大小写。 例如,conn和Conn被视为等效键。
2.如果在多个配置提供程序中设置了某一键和值,则会使用最后添加的提供程序中的值。
3.分层键
(1)在配置 API 中,冒号分隔符 (:
) 适用于所有平台。
(2)在环境变量中,冒号分隔符可能无法适用于所有平台。 所有平台均支持采用双下划线 __
,并且它会自动转换为冒号 :
。
(3)在 Azure Key Vault 中,分层键使用 --
作为分隔符。 当机密加载到应用的配置中时,Azure Key Vault 配置提供程序 会自动将 --
替换为 :
。
4.ConfigurationBinder 支持使用配置键中的数组索引将数组绑定到对象。
值:
1.为字符串。
2.NULL 值不能存储在配置中或绑定到对象。
一、默认配置
.Net Core的默认配置由CreateDefaultBuilder按照以下的顺序提供:
-
ChainedConfigurationProvider:添加现有 IConfiguration 作为源。 在默认配置示例中,添加主机配置,并将它设置为应用配置的第一个源。
-
使用JsonConfigurationProvider加载 appsettings.json 。
-
使用JsonConfigurationProvider加载 appsettings.Environment.json 。 例如,appsettings.Production.json 和 appsettings.Development.json 。
-
应用在 Development环境中运行时的应用机密。
-
使用环境变量配置提供程序通过环境变量提供。
-
使用命令行配置提供程序通过命令行参数提供。
后加载的配置会覆盖掉前面加载的配置。例如 appsettings.json和appsettings.Development.json都设置了一个叫MyKey的键,那获取到MyKey的值会是appsettings.Development.json配置的,如下:
appsettings.json的配置:
{
"MyKey": "Value" }
appsettings.Development.json的配置:
{
"MyKey": "developmentValue" }
在Startup.cs中运行:
app.Run(async context => { await context.Response.WriteAsync(Configuration["MyKey"]); });
得到结果:
二、使用选项模式绑定配置数据
选项模式是读取配置数据的首选方式,也就是把配置数据绑定到类对象上,这个类有几个要求:
1.必须是包含公共无参数构造函数的非抽象类。
2.类的属性必须有get和set。
绑定的方法使用IConfiguration的Configuration.GetSection(键名).Bind(对象)或者Configuration.GetSection(键名).Get<类>()。
我们在appsettings.json中加入以下数据:
"MyKey": { "Name": "my name is tom", "Age": "my age is 12" }
然后建立一个选项类MyOptions:
public class MyOptions { public string Name { get; set; } public string Age { get; set; } }
在Starup.cs中如下代码:
app.Run(async context => { MyOptions myOptions = new MyOptions(); Configuration.GetSection("MyKey").Bind(myOptions);
//Configuration.GetSection("MyKey").Get<MyOptions>(); await context.Response.WriteAsync(myOptions.Name + "," + myOptions.Age); });
运行可以看到输出结果。输出的结果会随这appsettings.json的配置更改而更改哦。
当然,我们还可以通过将选项类注入到依赖注入服务容器中,来实现绑定,如下。
services.Configure<MyOptions>(Configuration.GetSection("MyKey"));
但是,这种方式不会读取在应用启动后对 JSON 配置文件所做的更改。不过可以通过配置reloadOnChange: true来启用对应配置文件来实现,如下。
public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true); }) .UseStartup<Startup>();
三、配置环境变量
在window中环境变量在系统属性->环境变量中:
如图可以看到有一个环境变量叫NUMBER_OF_PROCESSORS、一个叫DriverData,我们可以直接获取DriverData,或通过AddEnvironmentVariables方法指定环境变量的前缀,在获取环境变量的值的时候会自动忽略前缀,如下。
public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.AddEnvironmentVariables("NUMBER_"); config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true); }) .UseStartup<Startup>();
app.Run(async context => { await context.Response.WriteAsync(Configuration["OF_PROCESSORS"]+","+Configuration["DriverData"]); });
运行可以得到结果:
在 launchSettings.json 中设置的环境变量将替代在系统环境中设置的变量。
四、加载配置文件
除了上面的加载方式和文件,我们还能加载自己创建的各类配置文件,可以是xml、json、ini,甚至是文件名。
public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { //加载ini config.AddIniFile("MyIniConfig.ini", optional: true, reloadOnChange: true); //加载json config.AddIniFile("MyJsonConfig.json", optional: true, reloadOnChange: true); //加载xml config.AddIniFile("MyXmlConfig.xml", optional: true, reloadOnChange: true); //文件名 var path = Path.Combine(Directory.GetCurrentDirectory(), "path/to/files"); config.AddKeyPerFile(directoryPath: path, optional: true); //内存 var Dict = new Dictionary<string, string> { {"MyKey", "Dictionary MyKey Value"}, {"Position:Title", "Dictionary_Title"}, {"Position:Name", "Dictionary_Name" }, {"Logging:LogLevel:Default", "Warning"} }; config.AddInMemoryCollection(Dict); }) .UseStartup<Startup>();
文件名以_下划线分隔,Key_Name相当于Key:Name。文件的directoryPath参数必须是绝对路径,第二个参数是目录的路径。