配置
分类: Asp.net Core入门 ◆ 标签: #Asp.Net core基础 #基础 #Web ◆ 发布于: 2023-06-04 20:24:03

ASP.net Core
基于Configuration Provider
提供配置服务,Configuration Provider
从配置源(Configuration source
)读取键值对的配置,并提供给Asp.net Core
。 默认支持如下的配置源:
- 配置文件: appsettings.json
- 环境变量
- Azure Key Vault
- Azure App Configuration服务
- 命令行参数
- 自定义的配置提供者
- 目录文件
- 内存对象
缺省配置
关于缺省的配置,我们从dotnet new
或者Visual Studio
创建的模板:
public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); }
CreateDefaultBuilder
按照如下的顺序向应用提供配置:
- 向应用中添加
ChainedConfigurationProvider
, 添加一个IConfiguration
的实例,并且向其中添加Host
的配置,并且将它设置为第一个配置源(需要注意的是Host的配置是从环境变量和命令行参数中读入的)。 - appsettings.json: 使用
JSON Configuration Provider
- appsetttings.{Environment}.json。
- App secrets (仅仅在开发环境下)
- 环境变量读入
- 命令行参数读入
Tips
需要注意添加的顺序,后面添加的如果有同样名称的配置,后面的覆盖前面的。
分层的配置
需要了解的是配置的键值形式:
- 键是分层的,在
ASP.net Core
中分层以冒号分隔,另外需要注意的环境变量中有些不一样的地方。 - 所有的配置值都是默认字符串类型。
关于键的分层,我们先看一个配置文件的例子:
"Position": { "Title": "Editor", "Name": "Joe Smith" }
这个配置里有两对配置,分别键值对应为:
key = "Position:Title", Value="Editor"
key = "Position:Name", Value="Joe Smith"
另外需要注意的是目前在大多数的配置提供者中都是以冒号":"来分隔,但是在环境变量里,冒号不是所有的平台都支持,但是双下划线所有平台都支持,并且环境变量里的双下划线"__" 会在ASP.net Core
里自动转为":"
另外需要注意的是,在.Net
中默认定义环境变量前缀为DOTNET__
, 在Asp.net Core
中环境变量前缀定义为`ASPNETCORE__'
所以上述的环境变量中可以这样定义:
export DOTNET_Position__Title="Editor" export DONTNET_Position__Name="Joe Smith"
或者在Asp.net Core
中:
export ASPNETCORE_Position__Title="Editor" export ASPNETCORE_Position__Name="Joe Smith"
需要注意的是这个默认的前缀是可以更改的,可以通过如下的形式进行更改:
public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.AddEnvironmentVariables(prefix: "MyCustomPrefix_"); }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); }
使用环境变量标识一个数组,例如:
{ "SmtpServer": "smtp.example.com", "Logging": [ { "Name": "ToEmail", "Level": "Critical", "Args": { "FromAddress": "MySystem@example.com", "ToAddress": "SRE@example.com" } }, { "Name": "ToConsole", "Level": "Information" } ] }
环境变量表示为:
setx SmtpServer=smtp.example.com
setx Logging__0__Name=ToEmail
setx Logging__0__Level=Critical
setx Logging__0__Args__FromAddress=MySystem@example.com
setx Logging__0__Args__ToAddress=SRE@example.com
setx Logging__1__Name=ToConsole
setx Logging__1__Level=Information
使用命令行参数
很简单,看两个例子:
dotnet run MyKey="My key from command line" Position:Title=Cmd Position:Name=Cmd_Rick
dotnet run /MyKey "Using /" /Position:Title=Cmd_ /Position:Name=Cmd_Rick
或者:
dotnet run --MyKey "Using --" --Position:Title=Cmd-- --Position:Name=Cmd--Rick
使用DI来使用配置服务
我们在Host
那一节里已经学习过了,配置服务是几个在Host
初始化的时候已经初始化的服务之一,因此它可以很容易的在Startup
所有方法中使用,我们来看一个简单的例子:
{ "Position": { "Title": "Editor", "Name": "Joe Smith" }, "MyKey": "My appsettings.json Value", "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*" }
我们看一下如何从DI中使用这个配置:
public class TestModel : PageModel { // requires using Microsoft.Extensions.Configuration; private readonly IConfiguration Configuration; public TestModel(IConfiguration configuration) { Configuration = configuration; } public ContentResult OnGet() { var myKeyValue = Configuration["MyKey"]; var title = Configuration["Position:Title"]; var name = Configuration["Position:Name"]; var defaultLogLevel = Configuration["Logging:LogLevel:Default"]; return Content($"MyKey value: {myKeyValue} \n" + $"Title: {title} \n" + $"Name: {name} \n" + $"Default Log Level: {defaultLogLevel}"); } }
键和值的说明
- 键和值都不区分大小写。
- 如果在多个配置提供者中提供了同样的键,那么按照之间的顺序,后面提供的值覆盖之前的配置提供者。
- 键的分级(分层)
- 在配置API中以冒号":"作为分层分隔符
- 在环境变量里使用双下划线作为分隔符"__"
- 在
Azure Key Vault
中,分层分隔符使用"--"- 配置绑定支持数组绑定,请参考之前的数组绑定的方法。
链接字符串 (Connect String)
在环境变量里有四类前缀的关于链接字符串的特殊变量,在环境变量里以:
- CUSTOMCONNSTR_{KEY}
- MYSQLCONNSTR_{KEY}
- SQLAZURECONNSTR_{KEY}
- SQLCONNSTR_{KEY}
这四中读入之后,移除前缀,后面的key
,放入到配置中的ConnectionStrings
节中。
文件配置源
文件配置源包括如下几种:
- INI文件配置源
- JSON文件配置源
- XML文件配置源
给出一个实例,如何添加新的配置提供者:
public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.Sources.Clear(); var env = hostingContext.HostingEnvironment; config.AddIniFile("MyIniConfig.ini", optional: true, reloadOnChange: true) .AddIniFile($"MyIniConfig.{env.EnvironmentName}.ini", optional: true, reloadOnChange: true); config.AddEnvironmentVariables(); if (args != null) { config.AddCommandLine(args); } }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); }
需要注意的是HostBuilder
的方法`ConfigureAppConfiguration(hostingcontext, config)
如下是INI文件的格式:
MyKey="MyIniConfig.ini Value" [Position] Title="My INI Config title" Name="My INI Config name" [Logging:LogLevel] Default=Information Microsoft=Warning
如下是XML的配置:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <section name="section0"> <key name="key0">value 00</key> <key name="key1">value 01</key> </section> <section name="section1"> <key name="key0">value 10</key> <key name="key1">value 11</key> </section> </configuration>
其他两种基本类似。
Kestrel
Endpoint配置
有三种方式用于配置Kestrel
的Endpoint:
- 扩展方法
UseUrls
- 命令行参数
---urls
- 环境变量
ASPNETCORE_URLS
- 配置文件
Examples:
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); webBuilder..UseUrls("http://*:5000;http://localhost:5001;https://hostname:5002"); });
dotnet run --urls="https://localhost:7777"
set Kestrel__Endpoints__Https__Url=https://localhost:8888
"Kestrel": { "Endpoints": { "Https": { "Url": "https://localhost:9999" } } }
IConfiguration
的方法
Configuration
提供了一些方法用户配置。
GetValue
实例:
public class TestNumModel : PageModel { private readonly IConfiguration Configuration; public TestNumModel(IConfiguration configuration) { Configuration = configuration; } public ContentResult OnGet() { var number = Configuration.GetValue<int>("NumberKey", 99); return Content($"{number}"); } }
GetSection, GetChildren, and Exists
我们按照上述顺序一一看下demo code:
public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.AddJsonFile("MySubsection.json", optional: true, reloadOnChange: true); }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); }
载入配置,并且配置了属性optional
, reloadOnChange
。
public class TestSectionModel : PageModel { private readonly IConfiguration Config; public TestSectionModel(IConfiguration configuration) { Config = configuration.GetSection("section1"); } public ContentResult OnGet() { return Content( $"section1:key0: '{Config["key0"]}'\n" + $"section1:key1: '{Config["key1"]}'"); } }
GetChildren
public class TestSection4Model : PageModel { private readonly IConfiguration Config; public TestSection4Model(IConfiguration configuration) { Config = configuration; } public ContentResult OnGet() { string s = null; 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"; } return Content(s); } }
存取配置值
Startup
类中
在Startup
类中存取配置。由于配置在host配置里就已经初始化了,因此在startup
类中可以通过DI存取:
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddRazorPages(); Console.WriteLine($"MyKey : {Configuration["MyKey"]}"); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { Console.WriteLine($"Position:Title : {Configuration["Position:Title"]}"); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); }); } }
Razor Page
中
先引用类:
@page @model Test5Model @using Microsoft.Extensions.Configuration @inject IConfiguration Configuration Configuration value for 'MyKey': @Configuration["MyKey"]
MVC View file
@using Microsoft.Extensions.Configuration @inject IConfiguration Configuration Configuration value for 'MyKey': @Configuration["MyKey"]
在控制器中添加配置值
关于这个部分可以参考基于Ihosting Startup 程序集
我们除了直接引用Iconfiguration
的程序实例之外,还可以使用Option模式
来存取配置,我们下一节来学习Options模式
。