ASP.NET Core 中的配置Configuration in ASP.NET Core

本文内容

作者:Rick AndersonKirk Larkin

ASP.NET Core 中的配置是使用一个或多个配置提供程序执行的。配置提供程序使用各种配置源从键值对读取配置数据:

  • 设置文件,例如 appsettings.json
  • 环境变量
  • Azure Key Vault
  • Azure 应用程序配置
  • 命令行参数
  • 已安装或已创建的自定义提供程序
  • 目录文件
  • 内存中的 .NET 对象

查看或下载示例代码如何下载

默认配置Default configuration

通过 dotnet new 或 Visual Studio 创建的 ASP.NET Core Web 应用会生成以下代码:

  1. public class Program
  2. {
  3. public static void Main(string[] args)
  4. {
  5. CreateHostBuilder(args).Build().Run();
  6. }
  7. public static IHostBuilder CreateHostBuilder(string[] args) =>
  8. Host.CreateDefaultBuilder(args)
  9. .ConfigureWebHostDefaults(webBuilder =>
  10. {
  11. webBuilder.UseStartup<Startup>();
  12. });
  13. }

CreateDefaultBuilder 按照以下顺序为应用提供默认配置:

若要详细了解 CreateDefaultBuilder,请参阅默认生成器设置

以下代码按添加顺序显示了已启用的配置提供程序:

  1. public class Index2Model : PageModel
  2. {
  3. private IConfigurationRoot ConfigRoot;
  4. public Index2Model(IConfiguration configRoot)
  5. {
  6. ConfigRoot = (IConfigurationRoot)configRoot;
  7. }
  8. public ContentResult OnGet()
  9. {
  10. string str = "";
  11. foreach (var provider in ConfigRoot.Providers.ToList())
  12. {
  13. str += provider.ToString() + "\n";
  14. }
  15. return Content(str);
  16. }
  17. }

appsettings.jsonappsettings.json

请考虑使用以下 appsettings.json 文件 :

  1. {
  2. "Position": {
  3. "Title": "编辑器",
  4. "Name": "Joe Smith"
  5. },
  6. "MyKey": "My appsettings.json Value",
  7. "Logging": {
  8. "LogLevel": {
  9. "Default": "Information",
  10. "Microsoft": "Warning",
  11. "Microsoft.Hosting.Lifetime": "Information"
  12. }
  13. },
  14. "AllowedHosts": "*"
  15. }

以下来自示例下载的代码显示了上述的一些配置设置:

  1. public class TestModel : PageModel
  2. {
  3. // requires using Microsoft.Extensions.Configuration;
  4. private readonly IConfiguration Configuration;
  5. public TestModel(IConfiguration configuration)
  6. {
  7. Configuration = configuration;
  8. }
  9. public ContentResult OnGet()
  10. {
  11. var myKeyValue = Configuration["MyKey"];
  12. var title = Configuration["Position:Title"];
  13. var name = Configuration["Position:Name"];
  14. var defaultLogLevel = Configuration["Logging:LogLevel:Default"];
  15. return Content($"MyKey value: {myKeyValue} \n" +
  16. $"Title: {title} \n" +
  17. $"Name: {name} \n" +
  18. $"Default Log Level: {defaultLogLevel}");
  19. }
  20. }

默认的 JsonConfigurationProvider 会按以下顺序加载配置:

  • appsettings.json
  • appsettings.Environment.json :例如,appsettings.Production.json 和 appsettings.Development.json 文件。文件的环境版本是根据 IHostingEnvironment.EnvironmentName 加载的。有关详细信息,请参阅 在 ASP.NET Core 中使用多个环境
    appsettings.Environment.json 值将替代 appsettings.json 中的密钥 。例如,默认情况下:
  • 在开发环境中,appsettings.Development.json 配置将覆盖在 appsettings.json 中找到的值 。
  • 在生产环境中,appsettings.Production.json 配置将覆盖在 appsettings.json 中找到的值 。例如,在将应用部署到 Azure 时。

使用选项模式绑定分层配置数据Bind hierarchical configuration data using the options pattern

读取相关配置值的首选方法是使用选项模式例如,若要读取以下配置值,请执行以下操作:

  1. "Position": {
  2. "Title": "Editor",
  3. "Name": "Joe Smith"
  4. }

创建以下 PositionOptions 类:

  1. public class PositionOptions
  2. {
  3. public string Title { get; set; }
  4. public string Name { get; set; }
  5. }

类型的所有公共读写属性均已绑定。不会绑定字段。

下面的代码:

  1. public class Test22Model : PageModel
  2. {
  3. private readonly IConfiguration Configuration;
  4. public Test22Model(IConfiguration configuration)
  5. {
  6. Configuration = configuration;
  7. }
  8. public ContentResult OnGet()
  9. {
  10. var positionOptions = new PositionOptions();
  11. Configuration.GetSection("Position").Bind(positionOptions);
  12. return Content($"Title: {positionOptions.Title} \n" +
  13. $"Name: {positionOptions.Name}");
  14. }
  15. }

ConfigurationBinder.Get<T> 绑定并返回指定的类型。使用 ConfigurationBinder.Get<T> 可能比使用 ConfigurationBinder.Bind 更方便。下面的代码演示如何将 ConfigurationBinder.Get<T>PositionOptions 类配合使用:

  1. public class Test21Model : PageModel
  2. {
  3. private readonly IConfiguration Configuration;
  4. public PositionOptions positionOptions { get; private set; }
  5. public Test21Model(IConfiguration configuration)
  6. {
  7. Configuration = configuration;
  8. }
  9. public ContentResult OnGet()
  10. {
  11. positionOptions = Configuration.GetSection("Position").Get<PositionOptions>();
  12. return Content($"Title: {positionOptions.Title} \n" +
  13. $"Name: {positionOptions.Name}");
  14. }
  15. }

使用选项模式时的替代方法是绑定 Position 部分并将它添加到依赖项注入服务容器在以下代码中,PositionOptions 已通过 Configure 被添加到了服务容器并已绑定到了配置:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.Configure<PositionOptions>(Configuration.GetSection("Position"));
  4. services.AddRazorPages();
  5. }

通过使用前面的代码,以下代码将读取位置选项:

  1. public class Test2Model : PageModel
  2. {
  3. private readonly PositionOptions _options;
  4. public Test2Model(IOptions<PositionOptions> options)
  5. {
  6. _options = options.Value;
  7. }
  8. public ContentResult OnGet()
  9. {
  10. return Content($"Title: {_options.Title} \n" +
  11. $"Name: {_options.Name}");
  12. }
  13. }

使用默认配置,会通过 reloadOnChange: true 启用 appsettings.json 和 appsettings.Environment.json 文件 。应用启动后,对 appsettings.json 和 appsettings.Environment.json 文件做出的更改将由 JSON 配置提供程序读取 。

有关添加其他 JSON 配置文件的信息,请参阅本文档中的 JSON 配置提供程序

安全和机密管理器Security and secret manager

配置数据指南:

  • 请勿在配置提供程序代码或纯文本配置文件中存储密码或其他敏感数据。机密管理器可用于存储开发环境中的机密。
  • 不要在开发或测试环境中使用生产机密。
  • 请在项目外部指定机密,避免将其意外提交到源代码存储库。

默认情况下机密管理器会在 appsettings.json 和 appsettings.Environment.json 之后读取配置设置 。

有关存储密码或其他敏感数据的详细信息:

Azure Key Vault 安全存储 ASP.NET Core 应用的应用机密。有关详细信息,请参阅 ASP.NET Core 中的 Azure Key Vault 配置提供程序

环境变量Environment variables

使用默认配置,EnvironmentVariablesConfigurationProvider 会在读取 appsettings.json、appsettings.Environment.json 和机密管理器后从环境变量键值对加载配置 。因此,从环境中读取的键值会替代从 appsettings.json、appsettings.Environment.json 和机密管理器中读取的值 。

所有平台上的环境变量分层键都不支持 : 分隔符。__(双下划线):

  • 受所有平台支持。例如,Bash 不支持 : 分隔符,但支持 __
  • 自动替换为 :

以下 set 命令:

  • 在 Windows 上设置上述示例的环境键和值。
  • 在使用示例下载时测试设置。dotnet run 命令必须在项目目录中运行。
  1. set MyKey="My key from Environment"
  2. set Position__Title=Environment_Editor
  3. set Position__Name=Environment_Rick
  4. dotnet run

前面的环境设置:

  • 仅在进程中设置,这些进程是从设置进程的命令窗口启动的。
  • 不会由通过 Visual Studio 启动的浏览器读取。

以下 setx 命令可用于在 Windows 上设置环境键和值。set 不同,setx 设置是持久的。/M 在系统环境中设置变量。如果未使用 /M 开关,则会设置用户环境变量。

  1. setx MyKey "My key from setx Environment" /M
  2. setx Position__Title Setx_Environment_Editor /M
  3. setx Position__Name Environment_Rick /M

测试前面的命令是否会替代 appsettings.json 和 appsettings.Environment.json:

  • 使用 Visual Studio:退出并重启 Visual Studio。
  • 使用 CLI:启动新的命令窗口并输入 dotnet run

使用字符串调用 AddEnvironmentVariables 以指定环境变量的前缀:

  1. public class Program
  2. {
  3. public static void Main(string[] args)
  4. {
  5. CreateHostBuilder(args).Build().Run();
  6. }
  7. public static IHostBuilder CreateHostBuilder(string[] args) =>
  8. Host.CreateDefaultBuilder(args)
  9. .ConfigureAppConfiguration((hostingContext, config) =>
  10. {
  11. config.AddEnvironmentVariables(prefix: "MyCustomPrefix_");
  12. })
  13. .ConfigureWebHostDefaults(webBuilder =>
  14. {
  15. webBuilder.UseStartup<Startup>();
  16. });
  17. }

在上述代码中:

前缀会在读取配置键值对时被去除。

以下命令对自定义前缀进行测试:

  1. set MyCustomPrefix_MyKey="My key with MyCustomPrefix_ Environment"
  2. set MyCustomPrefix_Position__Title=Editor_with_customPrefix
  3. set MyCustomPrefix_Position__Name=Environment_Rick_cp
  4. dotnet run

默认配置会加载前缀为 DOTNETASPNETCORE 的环境变量和命令行参数。DOTNETASPNETCORE 前缀会由 ASP.NET Core 用于主机和应用配置,但不用于用户配置。有关主机和应用配置的详细信息,请参阅 .NET 通用主机

Azure 应用服务上,选择“设置”>“配置”页面上的“新应用程序设置” 。Azure 应用服务应用程序设置:

  • 已静态加密且通过加密的通道进行传输。
  • 已作为环境变量公开。

有关详细信息,请参阅 Azure 应用:使用 Azure 门户替代应用配置

有关 Azure 数据库连接字符串的信息,请参阅连接字符串前缀

命令行Command-line

使用默认配置,CommandLineConfigurationProvider 会从以下配置源后的命令行参数键值对中加载配置:

默认情况下,在命令行上设置的配置值会替代通过所有其他配置提供程序设置的配置值。

命令行参数Command-line arguments

以下命令使用 = 设置键和值:

  1. dotnet run MyKey="My key from command line" Position:Title=Cmd Position:Name=Cmd_Rick

以下命令使用 / 设置键和值:

  1. dotnet run /MyKey "Using /" /Position:Title=Cmd_ /Position:Name=Cmd_Rick

以下命令使用 设置键和值:

  1. dotnet run --MyKey "Using --" --Position:Title=Cmd-- --Position:Name=Cmd--Rick

键值:

  • 必须后跟 =,或者当值后跟一个空格时,键必须具有一个 / 的前缀。
  • 如果使用 =,则不是必需的。例如 MySetting=

在同一命令中,请勿将使用 = 的命令行参数键值对与使用空格的键值对混合使用。

交换映射Switch mappings

交换映射支持键名替换逻辑 。提供针对 AddCommandLine 方法的交换替换字典。

当使用交换映射字典时,会检查字典中是否有与命令行参数提供的键匹配的键。如果在字典中找到了命令行键,则会传回字典值将键值对设置为应用的配置。对任何具有单划线 (-) 前缀的命令行键而言,交换映射都是必需的。

交换映射字典键规则:

  • 交换必须以 - 开头。
  • 交换映射字典不得包含重复键。

若要使用交换映射字典,请将它传递到对 AddCommandLine 的调用中:

  1. public class Program
  2. {
  3. public static void Main(string[] args)
  4. {
  5. CreateHostBuilder(args).Build().Run();
  6. }
  7. public static IHostBuilder CreateHostBuilder(string[] args)
  8. {
  9. var switchMappings = new Dictionary<string, string>()
  10. {
  11. { "-k1", "key1" },
  12. { "-k2", "key2" },
  13. { "--alt3", "key3" },
  14. { "--alt4", "key4" },
  15. { "--alt5", "key5" },
  16. { "--alt6", "key6" },
  17. };
  18. return Host.CreateDefaultBuilder(args)
  19. .ConfigureAppConfiguration((hostingContext, config) =>
  20. {
  21. config.AddCommandLine(args, switchMappings);
  22. })
  23. .ConfigureWebHostDefaults(webBuilder =>
  24. {
  25. webBuilder.UseStartup<Startup>();
  26. });
  27. }
  28. }

下面的代码显示了替换后的键的键值:

  1. public class Test3Model : PageModel
  2. {
  3. private readonly IConfiguration Config;
  4. public Test3Model(IConfiguration configuration)
  5. {
  6. Config = configuration;
  7. }
  8. public ContentResult OnGet()
  9. {
  10. return Content(
  11. $"Key1: '{Config["Key1"]}'\n" +
  12. $"Key2: '{Config["Key2"]}'\n" +
  13. $"Key3: '{Config["Key3"]}'\n" +
  14. $"Key4: '{Config["Key4"]}'\n" +
  15. $"Key5: '{Config["Key5"]}'\n" +
  16. $"Key6: '{Config["Key6"]}'");
  17. }
  18. }

运行以下命令以测试键替换:

  1. dotnet run -k1=value1 -k2 value2 --alt3=value2 /alt4=value3 --alt5 value5 /alt6 value6

注意:目前,= 不能用于设置带有单划线 - 的键替换值。请参阅此 GitHub 问题

以下命令可用于测试键替换:

  1. dotnet run -k1 value1 -k2 value2 --alt3=value2 /alt4=value3 --alt5 value5 /alt6 value6

对于使用交换映射的应用,调用 CreateDefaultBuilder 不应传递参数。CreateDefaultBuilder 方法的 AddCommandLine 调用不包括映射的交换,并且无法将交换映射字典传递给 CreateDefaultBuilder解决方案不是将参数传递给 CreateDefaultBuilder,而是允许 ConfigurationBuilder 方法的 AddCommandLine 方法处理参数和交换映射字典。

分层配置数据Hierarchical configuration data

配置 API 在配置键中使用分隔符来展平分层数据,以此来读取分层配置数据。

示例下载包含以下 appsettings.json 文件 :

  1. {
  2. "Position": {
  3. "Title": "编辑器",
  4. "Name": "Joe Smith"
  5. },
  6. "MyKey": "My appsettings.json Value",
  7. "Logging": {
  8. "LogLevel": {
  9. "Default": "Information",
  10. "Microsoft": "Warning",
  11. "Microsoft.Hosting.Lifetime": "Information"
  12. }
  13. },
  14. "AllowedHosts": "*"
  15. }

以下来自示例下载的代码显示了一些配置设置:

  1. public class TestModel : PageModel
  2. {
  3. // requires using Microsoft.Extensions.Configuration;
  4. private readonly IConfiguration Configuration;
  5. public TestModel(IConfiguration configuration)
  6. {
  7. Configuration = configuration;
  8. }
  9. public ContentResult OnGet()
  10. {
  11. var myKeyValue = Configuration["MyKey"];
  12. var title = Configuration["Position:Title"];
  13. var name = Configuration["Position:Name"];
  14. var defaultLogLevel = Configuration["Logging:LogLevel:Default"];
  15. return Content($"MyKey value: {myKeyValue} \n" +
  16. $"Title: {title} \n" +
  17. $"Name: {name} \n" +
  18. $"Default Log Level: {defaultLogLevel}");
  19. }
  20. }

读取分层配置数据的首选方法是使用选项模式。有关详细信息,请参阅本文档中的绑定分层配置数据

GetSectionGetChildren 方法可用于隔离各个节和配置数据中某节的子节。稍后将在 GetSection、GetChildren 和 Exists 中介绍这些方法。

配置键和值Configuration keys and values

配置键:

  • 不区分大小写。例如,ConnectionStringconnectionstring 被视为等效键。
  • 如果在多个配置提供程序中设置了某一键和值,则会使用最后添加的提供程序中的值。有关详细信息,请参阅默认配置
  • 分层键
    • 在配置 API 中,冒号分隔符 (:) 适用于所有平台。
    • 在环境变量中,冒号分隔符可能无法适用于所有平台。所有平台均支持采用双下划线 __,并且它会自动转换为冒号 :
    • 在 Azure Key Vault 中,分层键使用 作为分隔符。在机密加载到应用的配置中时,写入代码以用 : 替换
  • ConfigurationBinder 支持使用配置键中的数组索引将数组绑定到对象。数组绑定将在将数组绑定到类部分中进行介绍。

配置值:

  • 为字符串。
  • NULL 值不能存储在配置中或绑定到对象。

配置提供程序Configuration providers

下表显示了 ASP.NET Core 应用可用的配置提供程序。

提供程序通过以下对象提供配置
Azure Key Vault 配置提供程序Azure Key Vault
Azure 应用配置提供程序Azure 应用程序配置
命令行配置提供程序命令行参数
自定义配置提供程序自定义源
环境变量配置提供程序环境变量
文件配置提供程序INI、JSON 和 XML 文件
Key-per-file 配置提供程序目录文件
内存配置提供程序内存中集合
机密管理器用户配置文件目录中的文件

按照指定的配置提供程序的顺序读取配置源。代码中的配置提供程序应以特定顺序排列,从而满足应用所需的基础配置源的优先级。

配置提供程序的典型顺序为:

默认配置中使用了上述提供程序顺序。

连接字符串前缀Connection string prefixes

对于四个连接字符串环境变量,配置 API 具有特殊的处理规则。这些连接字符串涉及了为应用环境配置 Azure 连接字符串。使用默认配置或没有向 AddEnvironmentVariables 应用前缀时,具有表中所示前缀的环境变量将加载到应用中。

连接字符串前缀提供程序
CUSTOMCONNSTR自定义提供程序
MYSQLCONNSTRMySQL
SQLAZURECONNSTRAzure SQL 数据库
SQLCONNSTRSQL Server

当发现环境变量并使用表中所示的四个前缀中的任何一个加载到配置中时:

  • 通过删除环境变量前缀并添加配置键节 (ConnectionStrings) 来创建配置键。
  • 创建一个新的配置键值对,表示数据库连接提供程序(CUSTOMCONNSTR_ 除外,它没有声明的提供程序)。
环境变量键转换的配置键提供程序配置条目
CUSTOMCONNSTR{KEY}ConnectionStrings:{KEY}配置条目未创建。
MYSQLCONNSTR{KEY}ConnectionStrings:{KEY}键:ConnectionStrings:{KEY}ProviderName值:MySql.Data.MySqlClient
SQLAZURECONNSTR{KEY}ConnectionStrings:{KEY}键:ConnectionStrings:{KEY}ProviderName值:System.Data.SqlClient
SQLCONNSTR{KEY}ConnectionStrings:{KEY}键:ConnectionStrings:{KEY}_ProviderName值:System.Data.SqlClient

JSON 配置提供程序JSON configuration provider

JsonConfigurationProvider 从 JSON 文件键值对加载配置。

重载可以指定:

  • 文件是否可选。
  • 如果文件更改,是否重载配置。

考虑下列代码:

  1. public class Program
  2. {
  3. public static void Main(string[] args)
  4. {
  5. CreateHostBuilder(args).Build().Run();
  6. }
  7. public static IHostBuilder CreateHostBuilder(string[] args) =>
  8. Host.CreateDefaultBuilder(args)
  9. .ConfigureAppConfiguration((hostingContext, config) =>
  10. {
  11. config.AddJsonFile("MyConfig.json",
  12. optional: true,
  13. reloadOnChange: true);
  14. })
  15. .ConfigureWebHostDefaults(webBuilder =>
  16. {
  17. webBuilder.UseStartup<Startup>();
  18. });
  19. }

前面的代码:

通常情况下,你不会希望自定义 JSON 文件替代在环境变量配置提供程序命令行配置提供程序中设置的值。

以下代码会清除所有配置提供程序并添加多个配置提供程序:

  1. public class Program
  2. {
  3. public static void Main(string[] args)
  4. {
  5. CreateHostBuilder(args).Build().Run();
  6. }
  7. public static IHostBuilder CreateHostBuilder(string[] args) =>
  8. Host.CreateDefaultBuilder(args)
  9. .ConfigureAppConfiguration((hostingContext, config) =>
  10. {
  11. config.Sources.Clear();
  12. var env = hostingContext.HostingEnvironment;
  13. config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
  14. .AddJsonFile($"appsettings.{env.EnvironmentName}.json",
  15. optional: true, reloadOnChange: true);
  16. config.AddJsonFile("MyConfig.json", optional: true, reloadOnChange: true)
  17. .AddJsonFile($"MyConfig.{env.EnvironmentName}.json",
  18. optional: true, reloadOnChange: true);
  19. config.AddEnvironmentVariables();
  20. if (args != null)
  21. {
  22. config.AddCommandLine(args);
  23. }
  24. })
  25. .ConfigureWebHostDefaults(webBuilder =>
  26. {
  27. webBuilder.UseStartup<Startup>();
  28. });
  29. }

在前面的代码中,MyConfig.json 和 MyConfig.Environment.json 文件中的设置 :

示例下载包含以下 MyConfig.json 文件 :

  1. {
  2. "Position": {
  3. "Title": "“我的配置”标题",
  4. "Name": "My Config Smith"
  5. },
  6. "MyKey": "MyConfig.json Value",
  7. "Logging": {
  8. "LogLevel": {
  9. "Default": "Information",
  10. "Microsoft": "Warning",
  11. "Microsoft.Hosting.Lifetime": "Information"
  12. }
  13. },
  14. "AllowedHosts": "*"
  15. }

以下来自示例下载的代码显示了上述的一些配置设置:

  1. public class TestModel : PageModel
  2. {
  3. // requires using Microsoft.Extensions.Configuration;
  4. private readonly IConfiguration Configuration;
  5. public TestModel(IConfiguration configuration)
  6. {
  7. Configuration = configuration;
  8. }
  9. public ContentResult OnGet()
  10. {
  11. var myKeyValue = Configuration["MyKey"];
  12. var title = Configuration["Position:Title"];
  13. var name = Configuration["Position:Name"];
  14. var defaultLogLevel = Configuration["Logging:LogLevel:Default"];
  15. return Content($"MyKey value: {myKeyValue} \n" +
  16. $"Title: {title} \n" +
  17. $"Name: {name} \n" +
  18. $"Default Log Level: {defaultLogLevel}");
  19. }
  20. }

文件配置提供程序File configuration provider

FileConfigurationProvider 是从文件系统加载配置的基类。以下配置提供程序派生自 FileConfigurationProvider

INI 配置提供程序INI configuration provider

IniConfigurationProvider 在运行时从 INI 文件键值对加载配置。

以下代码会清除所有配置提供程序并添加多个配置提供程序:

  1. public class Program
  2. {
  3. public static void Main(string[] args)
  4. {
  5. CreateHostBuilder(args).Build().Run();
  6. }
  7. public static IHostBuilder CreateHostBuilder(string[] args) =>
  8. Host.CreateDefaultBuilder(args)
  9. .ConfigureAppConfiguration((hostingContext, config) =>
  10. {
  11. config.Sources.Clear();
  12. var env = hostingContext.HostingEnvironment;
  13. config.AddIniFile("MyIniConfig.ini", optional: true, reloadOnChange: true)
  14. .AddIniFile($"MyIniConfig.{env.EnvironmentName}.ini",
  15. optional: true, reloadOnChange: true);
  16. config.AddEnvironmentVariables();
  17. if (args != null)
  18. {
  19. config.AddCommandLine(args);
  20. }
  21. })
  22. .ConfigureWebHostDefaults(webBuilder =>
  23. {
  24. webBuilder.UseStartup<Startup>();
  25. });
  26. }

在前面的代码中,MyIniConfig.ini 和 MyIniConfig.Environment.ini 文件中的设置会被以下提供程序中的设置替代 :

示例下载包含以下 MyIniConfig.ini 文件 :

  1. MyKey="MyIniConfig.ini Value"
  2. [Position]
  3. Title="My INI Config title"
  4. Name="My INI Config name"
  5. [Logging:LogLevel]
  6. Default=Information
  7. Microsoft=Warning

以下来自示例下载的代码显示了上述的一些配置设置:

  1. public class TestModel : PageModel
  2. {
  3. // requires using Microsoft.Extensions.Configuration;
  4. private readonly IConfiguration Configuration;
  5. public TestModel(IConfiguration configuration)
  6. {
  7. Configuration = configuration;
  8. }
  9. public ContentResult OnGet()
  10. {
  11. var myKeyValue = Configuration["MyKey"];
  12. var title = Configuration["Position:Title"];
  13. var name = Configuration["Position:Name"];
  14. var defaultLogLevel = Configuration["Logging:LogLevel:Default"];
  15. return Content($"MyKey value: {myKeyValue} \n" +
  16. $"Title: {title} \n" +
  17. $"Name: {name} \n" +
  18. $"Default Log Level: {defaultLogLevel}");
  19. }
  20. }

XML 配置提供程序XML configuration provider

XmlConfigurationProvider 在运行时从 XML 文件键值对加载配置。

以下代码会清除所有配置提供程序并添加多个配置提供程序:

  1. public class Program
  2. {
  3. public static void Main(string[] args)
  4. {
  5. CreateHostBuilder(args).Build().Run();
  6. }
  7. public static IHostBuilder CreateHostBuilder(string[] args) =>
  8. Host.CreateDefaultBuilder(args)
  9. .ConfigureAppConfiguration((hostingContext, config) =>
  10. {
  11. config.Sources.Clear();
  12. var env = hostingContext.HostingEnvironment;
  13. config.AddXmlFile("MyXMLFile.xml", optional: true, reloadOnChange: true)
  14. .AddXmlFile($"MyXMLFile.{env.EnvironmentName}.xml",
  15. optional: true, reloadOnChange: true);
  16. config.AddEnvironmentVariables();
  17. if (args != null)
  18. {
  19. config.AddCommandLine(args);
  20. }
  21. })
  22. .ConfigureWebHostDefaults(webBuilder =>
  23. {
  24. webBuilder.UseStartup<Startup>();
  25. });
  26. }

在前面的代码中,MyXMLFile.xml 和 MyXMLFile.Environment.xml 文件中的设置会被以下提供程序中的设置替代 :

示例下载包含以下 MyXMLFile.xml 文件 :

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <configuration>
  3. <MyKey>MyXMLFile Value</MyKey>
  4. <Position>
  5. <Title>Title from MyXMLFile</Title>
  6. <Name>Name from MyXMLFile</Name>
  7. </Position>
  8. <Logging>
  9. <LogLevel>
  10. <Default>Information</Default>
  11. <Microsoft>Warning</Microsoft>
  12. </LogLevel>
  13. </Logging>
  14. </configuration>

以下来自示例下载的代码显示了上述的一些配置设置:

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}");
    }
}

如果使用 name 属性来区分元素,则使用相同元素名称的重复元素可以正常工作:

<?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>

以下代码会读取前面的配置文件并显示键和值:

public class IndexModel : PageModel
{
    private readonly IConfiguration Configuration;

    public IndexModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var key00 = "section:section0:key:key0";
        var key01 = "section:section0:key:key1";
        var key10 = "section:section1:key:key0";
        var key11 = "section:section1:key:key1";

        var val00 = Configuration[key00];
        var val01 = Configuration[key01];
        var val10 = Configuration[key10];
        var val11 = Configuration[key11];

        return Content($"{key00} value: {val00} \n" +
                       $"{key01} value: {val01} \n" +
                       $"{key10} value: {val10} \n" +
                       $"{key10} value: {val11} \n"
                       );
    }
}

属性可用于提供值:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <key attribute="value" />
  <section>
    <key attribute="value" />
  </section>
</configuration>

以前的配置文件使用 value 加载以下键:

  • key:attribute
  • section:key:attribute

Key-per-file 配置提供程序Key-per-file configuration provider

KeyPerFileConfigurationProvider 使用目录的文件作为配置键值对。该键是文件名。该值包含文件的内容。Key-per-file 配置提供程序用于 Docker 托管方案。

若要激活 Key-per-file 配置,请在 ConfigurationBuilder 的实例上调用 AddKeyPerFile 扩展方法。文件的 directoryPath 必须是绝对路径。

重载允许指定:

  • 配置源的 Action<KeyPerFileConfigurationSource> 委托。
  • 目录是否可选以及目录的路径。

双下划线字符 () 用作文件名中的配置键分隔符。例如,文件名 LoggingLogLevel__System 生成配置键 Logging:LogLevel:System

构建主机时调用 ConfigureAppConfiguration 以指定应用的配置:

.ConfigureAppConfiguration((hostingContext, config) =>
{
    var path = Path.Combine(
        Directory.GetCurrentDirectory(), "path/to/files");
    config.AddKeyPerFile(directoryPath: path, optional: true);
})

内存配置提供程序Memory configuration provider

MemoryConfigurationProvider 使用内存中集合作为配置键值对。

以下代码将内存集合添加到配置系统中:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        var Dict = new Dictionary<string, string>
        {
           {"MyKey", "Dictionary MyKey Value"},
           {"Position:Title", "Dictionary_Title"},
           {"Position:Name", "Dictionary_Name" },
           {"Logging:LogLevel:Default", "Warning"}
        };

        return Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddInMemoryCollection(Dict);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
    }
}

以下来自示例下载的代码显示了上述配置设置:

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}");
    }
}

在前面的代码中,config.AddInMemoryCollection(Dict) 会被添加到默认配置提供程序之后。有关对配置提供程序进行排序的示例,请参阅 JSON 配置提供程序

有关对配置提供程序进行排序的示例,请参阅 JSON 配置提供程序

有关使用 MemoryConfigurationProvider 的其他示例,请参阅绑定数组

GetValueGetValue

ConfigurationBinder.GetValue<T> 从配置中提取一个具有指定键的值,并将它转换为指定的类型:

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}");
    }
}

在前面的代码中,如果在配置中找不到 NumberKey,则使用默认值 99

GetSection、GetChildren 和 ExistsGetSection, GetChildren, and Exists

对于下面的示例,请考虑以下 MySubsection.json 文件 :

{
  "section0": {
    "key0": "value00",
    "key1": "value01"
  },
  "section1": {
    "key0": "value10",
    "key1": "value11"
  },
  "section2": {
    "subsection0": {
      "key0": "value200",
      "key1": "value201"
    },
    "subsection1": {
      "key0": "value210",
      "key1": "value211"
    }
  }
}

以下代码将 MySubsection.json 添加到配置提供程序 :

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>();
            });
}

GetSectionGetSection

IConfiguration.GetSection 会返回具有指定子节键的配置子节。

以下代码将返回 section1 的值:

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"]}'");
    }
}

以下代码将返回 section2:subsection0 的值:

public class TestSection2Model : PageModel
{
    private readonly IConfiguration Config;

    public TestSection2Model(IConfiguration configuration)
    {
        Config = configuration.GetSection("section2:subsection0");
    }

    public ContentResult OnGet()
    {
        return Content(
                $"section2:subsection0:key0 '{Config["key0"]}'\n" +
                $"section2:subsection0:key1:'{Config["key1"]}'");
    }
}

GetSection 永远不会返回 null如果找不到匹配的节,则返回空 IConfigurationSection

GetSection 返回匹配的部分时,Value 未填充。存在该部分时,返回一个 KeyPath 部分。

GetChildren 和 ExistsGetChildren and Exists

以下代码将调用 IConfiguration.GetChildren 并返回 section2:subsection0 的值:

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);
    }
}

前面的代码将调用 ConfigurationExtensions.Exists 以验证该节是否存在:

绑定数组Bind an array

ConfigurationBinder.Bind 支持使用配置键中的数组索引将数组绑定到对象。公开数值键段的任何数组格式都能够与 POCO 类数组进行数组绑定。

请考虑示例下载中的 MyArray.json :

{
  "array": {
    "entries": {
      "0": "value00",
      "1": "value10",
      "2": "value20",
      "4": "value40",
      "5": "value50"
    }
  }
}

以下代码将 MyArray.json 添加到配置提供程序 :

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("MyArray.json", 
                    optional: true, 
                    reloadOnChange: true);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

以下代码将读取配置并显示值:

public class ArrayModel : PageModel
{
    private readonly IConfiguration Config;
    public ArrayExample _array { get; private set; }

    public ArrayModel(IConfiguration config)
    {
        Config = config;
    }

    public ContentResult OnGet()
    {
        _array = Config.GetSection("array").Get<ArrayExample>();
        string s = null;

        for (int j = 0; j < _array.Entries.Length; j++)
        {
            s += $"Index: {j}  Value:  {_array.Entries[j]} \n";
        }

        return Content(s);
    }
}

前面的代码会返回以下输出:

Index: 0  Value: value00
Index: 1  Value: value10
Index: 2  Value: value20
Index: 3  Value: value40
Index: 4  Value: value50

在前面的输出中,索引 3 具有值 value40,与 MyArray.json 中的 "4": "value40", 相对应 。绑定的数组索引是连续的,并且未绑定到配置键索引。配置绑定器不能绑定 NULL 值,也不能在绑定的对象中创建 NULL 条目

以下代码将通过 AddInMemoryCollection 扩展方法加载 array:entries 配置:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        var arrayDict = new Dictionary<string, string>
        {
            {"array:entries:0", "value0"},
            {"array:entries:1", "value1"},
            {"array:entries:2", "value2"},
            //              3   Skipped
            {"array:entries:4", "value4"},
            {"array:entries:5", "value5"}
        };

        return Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddInMemoryCollection(arrayDict);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
    }
}

以下代码将读取 arrayDict Dictionary 中的配置并显示值:

public class ArrayModel : PageModel
{
    private readonly IConfiguration Config;
    public ArrayExample _array { get; private set; }

    public ArrayModel(IConfiguration config)
    {
        Config = config;
    }

    public ContentResult OnGet()
    {
        _array = Config.GetSection("array").Get<ArrayExample>();
        string s = null;

        for (int j = 0; j < _array.Entries.Length; j++)
        {
            s += $"Index: {j}  Value:  {_array.Entries[j]} \n";
        }

        return Content(s);
    }
}

前面的代码会返回以下输出:

Index: 0  Value: value0
Index: 1  Value: value1
Index: 2  Value: value2
Index: 3  Value: value4
Index: 4  Value: value5

绑定对象中的索引 #3 保留 array:4 配置键的配置数据及其值 value4当绑定包含数组的配置数据时,配置键中的数组索引用于在创建对象时迭代配置数据。无法在配置数据中保留 null 值,并且当配置键中的数组跳过一个或多个索引时,不会在绑定对象中创建 null 值条目。

可以在由任何读取索引 #3 键/值对的配置提供程序绑定到 ArrayExample 实例之前提供索引 #3 的缺失配置项。请考虑示例下载中的以下 Value3.json 文件 :

{
  "array:entries:3": "value3"
}

以下代码包含 Value3.json 和 arrayDict Dictionary 的配置 :

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        var arrayDict = new Dictionary<string, string>
        {
            {"array:entries:0", "value0"},
            {"array:entries:1", "value1"},
            {"array:entries:2", "value2"},
            //              3   Skipped
            {"array:entries:4", "value4"},
            {"array:entries:5", "value5"}
        };

        return Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddInMemoryCollection(arrayDict);
                config.AddJsonFile("Value3.json",
                                    optional: false, reloadOnChange: false);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
    }
}

以下代码将读取上述配置并显示值:

public class ArrayModel : PageModel
{
    private readonly IConfiguration Config;
    public ArrayExample _array { get; private set; }

    public ArrayModel(IConfiguration config)
    {
        Config = config;
    }

    public ContentResult OnGet()
    {
        _array = Config.GetSection("array").Get<ArrayExample>();
        string s = null;

        for (int j = 0; j < _array.Entries.Length; j++)
        {
            s += $"Index: {j}  Value:  {_array.Entries[j]} \n";
        }

        return Content(s);
    }
}

前面的代码会返回以下输出:

Index: 0  Value: value0
Index: 1  Value: value1
Index: 2  Value: value2
Index: 3  Value: value3
Index: 4  Value: value4
Index: 5  Value: value5

不需要自定义配置提供程序实现数组绑定。

自定义配置提供程序Custom configuration provider

该示例应用演示了如何使用实体框架 (EF) 创建从数据库读取配置键值对的基本配置提供程序。

提供程序具有以下特征:

  • EF 内存中数据库用于演示目的。若要使用需要连接字符串的数据库,请实现辅助 ConfigurationBuilder 以从另一个配置提供程序提供连接字符串。
  • 提供程序在启动时将数据库表读入配置。提供程序不会基于每个键查询数据库。
  • 未实现更改时重载,因此在应用启动后更新数据库对应用的配置没有任何影响。

定义用于在数据库中存储配置值的 EFConfigurationValue 实体。

Models/EFConfigurationValue.cs

public class EFConfigurationValue
{
    public string Id { get; set; }
    public string Value { get; set; }
}

添加 EFConfigurationContext 以存储和访问配置的值。

EFConfigurationProvider/EFConfigurationContext.cs

public class EFConfigurationContext : DbContext
{
    public EFConfigurationContext(DbContextOptions options) : base(options)
    {
    }

    public DbSet<EFConfigurationValue> Values { get; set; }
}

创建用于实现 IConfigurationSource 的类。

EFConfigurationProvider/EFConfigurationSource.cs

public class EFConfigurationSource : IConfigurationSource
{
    private readonly Action<DbContextOptionsBuilder> _optionsAction;

    public EFConfigurationSource(Action<DbContextOptionsBuilder> optionsAction)
    {
        _optionsAction = optionsAction;
    }

    public IConfigurationProvider Build(IConfigurationBuilder builder)
    {
        return new EFConfigurationProvider(_optionsAction);
    }
}

通过从 ConfigurationProvider 继承来创建自定义配置提供程序。当数据库为空时,配置提供程序将对其进行初始化。由于配置密钥不区分大小写,因此用来初始化数据库的字典是用不区分大小写的比较程序 (StringComparer.OrdinalIgnoreCase) 创建的。

EFConfigurationProvider/EFConfigurationProvider.cs

public class EFConfigurationProvider : ConfigurationProvider
{
    public EFConfigurationProvider(Action<DbContextOptionsBuilder> optionsAction)
    {
        OptionsAction = optionsAction;
    }

    Action<DbContextOptionsBuilder> OptionsAction { get; }

    // Load config data from EF DB.
    public override void Load()
    {
        var builder = new DbContextOptionsBuilder<EFConfigurationContext>();

        OptionsAction(builder);

        using (var dbContext = new EFConfigurationContext(builder.Options))
        {
            dbContext.Database.EnsureCreated();

            Data = !dbContext.Values.Any()
                ? CreateAndSaveDefaultValues(dbContext)
                : dbContext.Values.ToDictionary(c => c.Id, c => c.Value);
        }
    }

    private static IDictionary<string, string> CreateAndSaveDefaultValues(
        EFConfigurationContext dbContext)
    {
        // Quotes (c)2005 Universal Pictures: Serenity
        // https://www.uphe.com/movies/serenity
        var configValues = 
            new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
            {
                { "quote1", "I aim to misbehave." },
                { "quote2", "I swallowed a bug." },
                { "quote3", "You can't stop the signal, Mal." }
            };

        dbContext.Values.AddRange(configValues
            .Select(kvp => new EFConfigurationValue 
                {
                    Id = kvp.Key,
                    Value = kvp.Value
                })
            .ToArray());

        dbContext.SaveChanges();

        return configValues;
    }
}

可以使用 AddEFConfiguration 扩展方法将配置源添加到 ConfigurationBuilder

Extensions/EntityFrameworkExtensions.cs :

public static class EntityFrameworkExtensions
{
    public static IConfigurationBuilder AddEFConfiguration(
        this IConfigurationBuilder builder, 
        Action<DbContextOptionsBuilder> optionsAction)
    {
        return builder.Add(new EFConfigurationSource(optionsAction));
    }
}

下面的代码演示如何在 Program.cs 中使用自定义的 EFConfigurationProvider

public class Program
{
    public static Dictionary<string, string> arrayDict = 
        new Dictionary<string, string>
        {
            {"array:entries:0", "value0"},
            {"array:entries:1", "value1"},
            {"array:entries:2", "value2"},
            {"array:entries:4", "value4"},
            {"array:entries:5", "value5"}
        };

    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddInMemoryCollection(arrayDict);
                config.AddJsonFile(
                    "json_array.json", optional: false, reloadOnChange: false);
                config.AddJsonFile(
                    "starship.json", optional: false, reloadOnChange: false);
                config.AddXmlFile(
                    "tvshow.xml", optional: false, reloadOnChange: false);
                config.AddEFConfiguration(
                    options => options.UseInMemoryDatabase("InMemoryDb"));
                config.AddCommandLine(args);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

访问 Startup 中的配置Access configuration in Startup

以下代码显示 Startup 方法中的配置数据:

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 Pages 中的配置Access configuration in Razor Pages

以下代码显示 Razor 页面中的配置数据:

@page
@model Test5Model
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

Configuration value for 'MyKey': @Configuration["MyKey"]

访问 MVC 视图文件中的配置Access configuration in a MVC view file

以下代码显示 MVC 视图中的配置数据:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

Configuration value for 'MyKey': @Configuration["MyKey"]

主机与应用配置Host versus app configuration

在配置并启动应用之前,配置并启动主机 。主机负责应用程序启动和生存期管理。应用和主机均使用本主题中所述的配置提供程序进行配置。应用的配置中也包含主机配置键值对。有关在构建主机时如何使用配置提供程序以及配置源如何影响主机配置的详细信息,请参阅 ASP.NET Core 基础知识

默认主机配置Default host configuration

有关使用 Web 主机时默认配置的详细信息,请参阅本主题的 ASP.NET Core 2.2 版本

  • 主机配置通过以下方式提供:
  • 已建立 Web 主机默认配置 (ConfigureWebHostDefaults):
    • Kestrel 用作 Web 服务器,并使用应用的配置提供程序对其进行配置。
    • 添加主机筛选中间件。
    • 如果 ASPNETCORE_FORWARDEDHEADERS_ENABLED 环境变量设置为 true,则添加转发的标头中间件。
    • 启用 IIS 集成。

其他配置Other configuration

本主题仅与应用配置相关 。运行和托管 ASP.NET Core 应用的其他方面是使用本主题中未包含的配置文件进行配置:

若要详细了解如何从旧版 ASP.NET 迁移应用配置,请参阅 从 ASP.NET 迁移到 ASP.NET Core

从外部程序集添加配置Add configuration from an external assembly

通过 IHostingStartup 实现,可在启动时从应用 Startup 类之外的外部程序集向应用添加增强功能。有关详细信息,请参阅 在 ASP.NET Core 中使用承载启动程序集

其他资源Additional resources

ASP.NET Core 中的应用配置基于配置提供程序 建立的键值对。配置提供程序将配置数据从各种配置源读取到键值对:

  • Azure Key Vault
  • Azure 应用程序配置
  • 命令行参数
  • (已安装或已创建的)自定义提供程序
  • 目录文件
  • 环境变量
  • 内存中的 .NET 对象
  • 设置文件

Microsoft.AspNetCore.App metapackage 中包含通用配置提供程序方案的配置包 (Microsoft Extensions.Configuration)。

后面的代码示例和示例应用中的代码示例使用 Microsoft.Extensions.Configuration 命名空间:

using Microsoft.Extensions.Configuration;

选项模式 是本主题中描述的配置概念的扩展。选项使用类来表示相关设置的组。有关详细信息,请参阅 ASP.NET Core 中的选项模式

查看或下载示例代码如何下载

主机与应用配置Host versus app configuration

在配置并启动应用之前,配置并启动主机 。主机负责应用程序启动和生存期管理。应用和主机均使用本主题中所述的配置提供程序进行配置。应用的配置中也包含主机配置键值对。有关在构建主机时如何使用配置提供程序以及配置源如何影响主机配置的详细信息,请参阅 ASP.NET Core 基础知识

其他配置Other configuration

本主题仅与应用配置相关 。运行和托管 ASP.NET Core 应用的其他方面是使用本主题中未包含的配置文件进行配置:

若要详细了解如何从旧版 ASP.NET 迁移应用配置,请参阅 从 ASP.NET 迁移到 ASP.NET Core

默认配置Default configuration

基于 ASP.NET Core dotnet new模板的 Web 应用在生成主机时会调用 CreateDefaultBuilderCreateDefaultBuilder 按照以下顺序为应用提供默认配置:

以下内容适用于使用 Web 主机的应用。有关使用通用主机时默认配置的详细信息,请参阅本主题的最新版本

安全性Security

采用以下做法来保护敏感配置数据:

  • 请勿在配置提供程序代码或纯文本配置文件中存储密码或其他敏感数据。
  • 不要在开发或测试环境中使用生产机密。
  • 请在项目外部指定机密,避免将其意外提交到源代码存储库。

有关详细信息,请参阅下列主题:

Azure Key Vault 安全存储 ASP.NET Core 应用的应用机密。有关详细信息,请参阅 ASP.NET Core 中的 Azure Key Vault 配置提供程序

分层配置数据Hierarchical configuration data

配置 API 能够通过在配置键中使用分隔符来展平分层数据以保持分层配置数据。

在以下 JSON 文件中,两个节的结构化层次结构中存在四个键:

{
  "section0": {
    "key0": "value",
    "key1": "value"
  },
  "section1": {
    "key0": "value",
    "key1": "value"
  }
}

将文件读入配置时,将创建唯一键以保持配置源的原始分层数据结构。使用冒号 (:) 展平节和键以保持原始结构:

  • section0:key0
  • section0:key1
  • section1:key0
  • section1:key1

GetSectionGetChildren 方法可用于隔离各个节和配置数据中某节的子节。稍后将在 GetSection、GetChildren 和 Exists 中介绍这些方法。

约定Conventions

源和提供程序Sources and providers

在应用启动时,将按照指定的配置提供程序的顺序读取配置源。

实现更改检测的配置提供程序能够在基础设置更改时重新加载配置。例如,文件配置提供程序(本主题后面将对此进行介绍)和 Azure Key Vault 配置提供程序实现更改检测。

应用的依赖关系注入 (DI) 容器中提供了 IConfigurationIConfiguration 可注入到 Razor Pages PageModel 或 MVC Controller 来获取以下类的配置。

在下面的示例中,使用 _config 字段来访问配置值:

public class IndexModel : PageModel
{
    private readonly IConfiguration _config;

    public IndexModel(IConfiguration config)
    {
        _config = config;
    }
}
public class HomeController : Controller
{
    private readonly IConfiguration _config;

    public HomeController(IConfiguration config)
    {
        _config = config;
    }
}

配置提供程序不能使用 DI,因为主机在设置这些提供程序时 DI 不可用。

键Keys

配置键采用以下约定:

  • 键不区分大小写。例如,ConnectionStringconnectionstring 被视为等效键。
  • 如果由相同或不同的配置提供程序设置相同键的值,则键上设置的最后一个值就是所使用的值。
  • 分层键
    • 在配置 API 中,冒号分隔符 (:) 适用于所有平台。
    • 在环境变量中,冒号分隔符可能无法适用于所有平台。所有平台均支持采用双下划线 (__),并可以将其自动转换为冒号。
    • 在 Azure Key Vault 中,分层键使用 (两个破折号)作为分隔符。将机密加载到应用的配置中时,用冒号替换破折号。
  • ConfigurationBinder 支持使用配置键中的数组索引将数组绑定到对象。数组绑定将在将数组绑定到类部分中进行介绍。

值Values

配置值采用以下约定:

  • 值是字符串。
  • NULL 值不能存储在配置中或绑定到对象。

提供程序Providers

下表显示了 ASP.NET Core 应用可用的配置提供程序。

提供程序通过以下对象提供配置…
Azure Key Vault 配置提供程序(安全 主题)Azure Key Vault
Azure 应用程序配置提供程序(Azure 文档)Azure 应用程序配置
命令行配置提供程序命令行参数
自定义配置提供程序自定义源
环境变量配置提供程序环境变量
文件配置提供程序文件(INI、JSON、XML)
Key-per-file 配置提供程序目录文件
内存配置提供程序内存中集合
用户机密 (Secret Manager)(安全 主题)用户配置文件目录中的文件

按照启动时指定的配置提供程序的顺序读取配置源。本主题中所述的配置提供程序按字母顺序进行介绍,而不是按代码排列顺序进行介绍。代码中的配置提供程序应以特定顺序排列,从而满足应用所需的基础配置源的优先级。

配置提供程序的典型顺序为:

  • 文件(appsettings.json、appsettings.{Environment}.json,其中 {Environment} 是应用的当前托管环境)
  • Azure 密钥保管库
  • 用户机密 (Secret Manager)(仅限开发环境中)
  • 环境变量
  • 命令行参数
    通常的做法是将命令行配置提供程序置于一系列提供程序的末尾,以允许命令行参数替代由其他提供程序设置的配置。

使用 CreateDefaultBuilder 初始化新的主机生成器时,将使用上述提供程序序列。有关详细信息,请参阅默认配置部分。

用 UseConfiguration 配置主机生成器Configure the host builder with UseConfiguration

若要配置主机生成器,请使用配置在主机生成器上调用 UseConfiguration

public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
    var dict = new Dictionary<string, string>
    {
        {"MemoryCollectionKey1", "value1"},
        {"MemoryCollectionKey2", "value2"}
    };

    var config = new ConfigurationBuilder()
        .AddInMemoryCollection(dict)
        .Build();

    return WebHost.CreateDefaultBuilder(args)
        .UseConfiguration(config)
        .UseStartup<Startup>();
}

ConfigureAppConfigurationConfigureAppConfiguration

构建主机时调用 ConfigureAppConfiguration 以指定应用的配置提供程序以及 CreateDefaultBuilder 自动添加的配置提供程序:

public class Program
{
    public static Dictionary<string, string> arrayDict = 
        new Dictionary<string, string>
        {
            {"array:entries:0", "value0"},
            {"array:entries:1", "value1"},
            {"array:entries:2", "value2"},
            {"array:entries:4", "value4"},
            {"array:entries:5", "value5"}
        };

    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddInMemoryCollection(arrayDict);
                config.AddJsonFile(
                    "json_array.json", optional: false, reloadOnChange: false);
                config.AddJsonFile(
                    "starship.json", optional: false, reloadOnChange: false);
                config.AddXmlFile(
                    "tvshow.xml", optional: false, reloadOnChange: false);
                config.AddEFConfiguration(
                    options => options.UseInMemoryDatabase("InMemoryDb"));
                config.AddCommandLine(args);
            })
            .UseStartup<Startup>();
}

用命令行参数替代以前的配置Override previous configuration with command-line arguments

若要提供命令行参数可替代的应用配置,最后请调用 AddCommandLine

.ConfigureAppConfiguration((hostingContext, config) =>
{
    // Call other providers here
    config.AddCommandLine(args);
})

删除 CreateDefaultBuilder 添加的提供程序Remove providers added by CreateDefaultBuilder

要删除 CreateDefaultBuilder 添加的提供程序,请先对 IConfigurationBuilder.Sources 调用 Clear

.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.Sources.Clear();
    // Add providers here
})

在应用启动期间使用配置Consume configuration during app startup

在应用启动期间,可以使用 ConfigureAppConfiguration 中提供给应用的配置,包括 Startup.ConfigureServices有关详细信息,请参阅在启动期间访问配置部分。

命令行配置提供程序Command-line Configuration Provider

CommandLineConfigurationProvider 在运行时从命令行参数键值对加载配置。

要激活命令行配置,请在 ConfigurationBuilder 的实例上调用 AddCommandLine 扩展方法。

调用 CreateDefaultBuilder(string []) 时会自动调用 AddCommandLine有关详细信息,请参阅默认配置部分。

此外,CreateDefaultBuilder 也会加载:

  • appsettings.json 和 appsettings.{Environment}.json 文件中的可选配置 。
  • 用户机密 (Secret Manager)(在开发环境中)。
  • 环境变量。

CreateDefaultBuilder 最后添加命令行配置提供程序。在运行时传递的命令行参数会替代由其他提供程序设置的配置。

CreateDefaultBuilder 在构造主机时起作用。因此,CreateDefaultBuilder 激活的命令行配置可能会影响主机的配置方式。

对于基于 ASP.NET Core 模板的应用,CreateDefaultBuilder 已调用 AddCommandLine若要添加其他配置提供程序并保持能够用命令行参数替代这些提供程序的配置,请在 ConfigureAppConfiguration 中调用应用的其他提供程序,并最后调用 AddCommandLine

.ConfigureAppConfiguration((hostingContext, config) =>
{
    // Call other providers here
    config.AddCommandLine(args);
})

示例

示例应用利用静态便捷方法 CreateDefaultBuilder 来生成主机,其中包括一个对 AddCommandLine 的调用。

  • 在项目的目录中打开命令提示符。
  • dotnet run 命令提供命令行参数 dotnet run CommandLineKey=CommandLineValue
  • 应用运行后,在 http://localhost:5000 打开应用的浏览器。
  • 观察输出是否包含提供给 dotnet run 的配置命令行参数的键值对。

自变量Arguments

该值必须后跟一个等号 (=),否则当值后跟一个空格时,键必须具有前缀(/)。如果使用等号(例如 CommandLineKey=),则不需要该值。

键前缀示例
无前缀CommandLineKey1=value1
双划线 ()—CommandLineKey2=value2—CommandLineKey2 value2
正斜杠 (/)/CommandLineKey3=value3/CommandLineKey3 value3

在同一命令中,不要将使用等号的命令行参数键值对与使用空格的键值对混合使用。

示例命令:

dotnet run CommandLineKey1=value1 --CommandLineKey2=value2 /CommandLineKey3=value3
dotnet run --CommandLineKey1 value1 /CommandLineKey2 value2
dotnet run CommandLineKey1= CommandLineKey2=value2

交换映射Switch mappings

交换映射支持键名替换逻辑。使用 ConfigurationBuilder 手动构建配置时,需要为 AddCommandLine 方法提供交换替换字典。

当使用交换映射字典时,会检查字典中是否有与命令行参数提供的键匹配的键。如果在字典中找到命令行键,则传回字典值(键替换)以将键值对设置为应用的配置。对任何具有单划线 (-) 前缀的命令行键而言,交换映射都是必需的。

交换映射字典键规则:

  • 交换必须以单划线 (-) 或双划线 () 开头。
  • 交换映射字典不得包含重复键。

创建交换映射字典。在以下示例中,创建了两个交换映射:

public static readonly Dictionary<string, string> _switchMappings = 
    new Dictionary<string, string>
    {
        { "-CLKey1", "CommandLineKey1" },
        { "-CLKey2", "CommandLineKey2" }
    };

生成主机后,使用交换映射字典来调用 AddCommandLine

.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.AddCommandLine(args, _switchMappings);
})

对于使用交换映射的应用,调用 CreateDefaultBuilder 不应传递参数。CreateDefaultBuilder 方法的 AddCommandLine 调用不包括映射的交换,并且无法将交换映射字典传递给 CreateDefaultBuilder解决方案不是将参数传递给 CreateDefaultBuilder,而是允许 ConfigurationBuilder 方法的 AddCommandLine 方法处理参数和交换映射字典。

创建交换映射字典后,它将包含下表所示的数据。

“值”
-CLKey1CommandLineKey1
-CLKey2CommandLineKey2

如果在启动应用时使用了交换映射的键,则配置将接收字典提供的密钥上的配置值:

dotnet run -CLKey1=value1 -CLKey2=value2

运行上述命令后,配置包含下表中显示的值。

“值”
CommandLineKey1value1
CommandLineKey2value2

环境变量配置提供程序Environment Variables Configuration Provider

EnvironmentVariablesConfigurationProvider 在运行时从环境变量键值对加载配置。

要激活环境变量配置,请在 ConfigurationBuilder 的实例上调用 AddEnvironmentVariables 扩展方法。

所有平台上的环境变量分层键都不支持 : 分隔符。__(双下划线):

  • 受所有平台支持。例如,Bash 不支持 : 分隔符,但支持 __
  • 自动替换为 :

借助 Azure 应用服务,可在 Azure 门户中设置使用环境变量配置提供程序替代应用配置的环境变量。有关详细信息,请参阅 Azure 应用:使用 Azure 门户替代应用配置

如果使用 Web 主机初始化新的主机生成器,且调用 CreateDefaultBuilder,则使用 AddEnvironmentVariables主机配置加载前缀为 ASPNETCORE_ 的环境变量。有关详细信息,请参阅默认配置部分。

此外,CreateDefaultBuilder 也会加载:

  • 来自没有前缀的环境变量的应用配置,方法是通过调用不带前缀的 AddEnvironmentVariables
  • appsettings.json 和 appsettings.{Environment}.json 文件中的可选配置 。
  • 用户机密 (Secret Manager)(在开发环境中)。
  • 命令行参数。

环境变量配置提供程序是在配置已根据用户机密和 appsettings 文件建立后调用。在此位置调用提供程序允许在运行时读取的环境变量替代由用户机密和 appsettings 文件设置的配置。

要从其他环境变量提供应用配置,请在 ConfigureAppConfiguration 中调用应用的其他提供程序,并使用前缀调用 AddEnvironmentVariables

.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.AddEnvironmentVariables(prefix: "PREFIX_");
})

最后调用 AddEnvironmentVariables让带给定前缀的环境变量可替代其他提供程序中的值。

示例

示例应用利用静态便捷方法 CreateDefaultBuilder 来生成主机,其中包括一个对 AddEnvironmentVariables 的调用。

  • 运行示例应用。在 http://localhost:5000 打开应用的浏览器。
  • 观察输出是否包含环境变量 ENVIRONMENT 的键值对。该值反映了应用运行的环境,在本地运行时通常为 Development
    为了缩短应用呈现的环境变量列表,应用会筛选环境变量。请参阅示例应用的“Pages/Index.cshtml.cs”文件 。

要公开应用可用的所有环境变量,请将 Pages/Index.cshtml.cs 中的 FilteredConfiguration 更改为以下内容 :

FilteredConfiguration = _config.AsEnumerable();

前缀Prefixes

AddEnvironmentVariables 方法提供前缀时,将筛选加载到应用的配置中的环境变量。例如,要筛选前缀 CUSTOM_ 上的环境变量,请将前缀提供给配置提供程序:

var config = new ConfigurationBuilder()
    .AddEnvironmentVariables("CUSTOM_")
    .Build();

创建配置键值对时,将去除前缀。

若已创建主机生成器,则主机配置由环境变量提供。有关用于这些环境变量的前缀的详细信息,请参阅默认配置部分。

连接字符串前缀

针对为应用环境配置 Azure 连接字符串所涉及的四个连接字符串环境变量,配置 API 具有特殊的处理规则。如果没有向 AddEnvironmentVariables 提供前缀,则具有表中所示前缀的环境变量将加载到应用中。

连接字符串前缀提供程序
CUSTOMCONNSTR自定义提供程序
MYSQLCONNSTRMySQL
SQLAZURECONNSTRAzure SQL 数据库
SQLCONNSTRSQL Server

当发现环境变量并使用表中所示的四个前缀中的任何一个加载到配置中时:

  • 通过删除环境变量前缀并添加配置键节 (ConnectionStrings) 来创建配置键。
  • 创建一个新的配置键值对,表示数据库连接提供程序(CUSTOMCONNSTR_ 除外,它没有声明的提供程序)。
环境变量键转换的配置键提供程序配置条目
CUSTOMCONNSTR{KEY}ConnectionStrings:{KEY}配置条目未创建。
MYSQLCONNSTR{KEY}ConnectionStrings:{KEY}键:ConnectionStrings:{KEY}ProviderName值:MySql.Data.MySqlClient
SQLAZURECONNSTR{KEY}ConnectionStrings:{KEY}键:ConnectionStrings:{KEY}ProviderName值:System.Data.SqlClient
SQLCONNSTR{KEY}ConnectionStrings:{KEY}键:ConnectionStrings:{KEY}_ProviderName值:System.Data.SqlClient

示例

在服务器上创建了一个自定义连接字符串环境变量:

  • 名称 – CUSTOMCONNSTR_ReleaseDB
  • 值 – Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True

如果 IConfiguration 已引入并分配给名为 _config 的字段,请读取值:

_config["ConnectionStrings:ReleaseDB"]

文件配置提供程序File Configuration Provider

FileConfigurationProvider 是从文件系统加载配置的基类。以下配置提供程序专用于特定文件类型:

INI 配置提供程序INI Configuration Provider

IniConfigurationProvider 在运行时从 INI 文件键值对加载配置。

若要激活 INI 文件配置,请在 ConfigurationBuilder 的实例上调用 AddIniFile 扩展方法。

冒号可用作 INI 文件配置中的节分隔符。

重载允许指定:

  • 文件是否可选。
  • 如果文件更改,是否重载配置。
  • IFileProvider 用于访问该文件。

构建主机时调用 ConfigureAppConfiguration 以指定应用的配置:

.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.AddIniFile(
        "config.ini", optional: true, reloadOnChange: true);
})

INI 配置文件的通用示例:

[section0]
key0=value
key1=value

[section1]
subsection:key=value

[section2:subsection0]
key=value

[section2:subsection1]
key=value

以前的配置文件使用 value 加载以下键:

  • section0:key0
  • section0:key1
  • section1:subsection:key
  • section2:subsection0:key
  • section2:subsection1:key

JSON 配置提供程序JSON Configuration Provider

JsonConfigurationProvider 在运行时期间从 JSON 文件键值对加载配置。

若要激活 JSON 文件配置,请在 ConfigurationBuilder 的实例上调用 AddJsonFile 扩展方法。

重载允许指定:

  • 文件是否可选。
  • 如果文件更改,是否重载配置。
  • IFileProvider 用于访问该文件。

使用 CreateDefaultBuilder 初始化新的主机生成器时,会自动调用两次 AddJsonFile调用该方法来从以下文件加载配置:

  • appsettings.json – 首先读取此文件 。该文件的环境版本可以替代 appsettings.json 文件提供的值。
  • appsettings.{Environment}.json – 根据 IHostingEnvironment.EnvironmentName 加载文件的环境版本 。

有关详细信息,请参阅默认配置部分。

此外,CreateDefaultBuilder 也会加载:

首先建立 JSON 配置提供程序。因此,用户机密、环境变量和命令行参数会替代由 appsettings 文件设置的配置。

构建主机时调用 ConfigureAppConfiguration 以指定除 appsettings.json 和 appsettings.{Environment}.json 以外的文件的应用配置:

.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.AddJsonFile(
        "config.json", optional: true, reloadOnChange: true);
})

示例

示例应用利用静态便捷方法 CreateDefaultBuilder 来生成主机,其中包括两个对 AddJsonFile 的调用:

  • 第一次调用 AddJsonFile 会从 appsettings 加载配置 :
{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*"
}
  • 第二次调用 AddJsonFile 会从 appsettings.{Environment}.json 加载配置 。对于示例应用中的 appsettings.Development.json,将加载以下文件 :
{
  "Logging": {
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  }
}
  • 运行示例应用。在 http://localhost:5000 打开应用的浏览器。
  • 输出包含配置的键值对(由应用的环境而定)。在开发环境中运行应用时,键 Logging:LogLevel:Default 的日志级别为 Debug
  • 再次在生产环境中运行示例应用:
    • 打开 Properties/launchSettings.json 文件 。
    • ConfigurationSample 配置文件中,将 ASPNETCORE_ENVIRONMENT 环境变量的值更改为 Production
    • 保存文件,然后在命令外壳中使用 dotnet run 运行应用。
  • appsettings.Development.json 中的设置不再替代 appsettings.json 中的设置 。键 Logging:LogLevel:Default 的日志级别为 Warning

XML 配置提供程序XML Configuration Provider

XmlConfigurationProvider 在运行时从 XML 文件键值对加载配置。

若要激活 XML 文件配置,请在 ConfigurationBuilder 的实例上调用 AddXmlFile 扩展方法。

重载允许指定:

  • 文件是否可选。
  • 如果文件更改,是否重载配置。
  • IFileProvider 用于访问该文件。

创建配置键值对时,将忽略配置文件的根节点。不要在文件中指定文档类型定义 (DTD) 或命名空间。

构建主机时调用 ConfigureAppConfiguration 以指定应用的配置:

.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.AddXmlFile(
        "config.xml", optional: true, reloadOnChange: true);
})

XML 配置文件可以为重复节使用不同的元素名称:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <section0>
    <key0>value</key0>
    <key1>value</key1>
  </section0>
  <section1>
    <key0>value</key0>
    <key1>value</key1>
  </section1>
</configuration>

以前的配置文件使用 value 加载以下键:

  • section0:key0
  • section0:key1
  • section1:key0
  • section1:key1

如果使用 name 属性来区分元素,则使用相同元素名称的重复元素可以正常工作:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <section name="section0">
    <key name="key0">value</key>
    <key name="key1">value</key>
  </section>
  <section name="section1">
    <key name="key0">value</key>
    <key name="key1">value</key>
  </section>
</configuration>

以前的配置文件使用 value 加载以下键:

  • section:section0:key:key0
  • section:section0:key:key1
  • section:section1:key:key0
  • section:section1:key:key1

属性可用于提供值:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <key attribute="value" />
  <section>
    <key attribute="value" />
  </section>
</configuration>

以前的配置文件使用 value 加载以下键:

  • key:attribute
  • section:key:attribute

Key-per-file 配置提供程序Key-per-file Configuration Provider

KeyPerFileConfigurationProvider 使用目录的文件作为配置键值对。该键是文件名。该值包含文件的内容。Key-per-file 配置提供程序用于 Docker 托管方案。

若要激活 Key-per-file 配置,请在 ConfigurationBuilder 的实例上调用 AddKeyPerFile 扩展方法。文件的 directoryPath 必须是绝对路径。

重载允许指定:

  • 配置源的 Action<KeyPerFileConfigurationSource> 委托。
  • 目录是否可选以及目录的路径。

双下划线字符 () 用作文件名中的配置键分隔符。例如,文件名 LoggingLogLevel__System 生成配置键 Logging:LogLevel:System

构建主机时调用 ConfigureAppConfiguration 以指定应用的配置:

.ConfigureAppConfiguration((hostingContext, config) =>
{
    var path = Path.Combine(
        Directory.GetCurrentDirectory(), "path/to/files");
    config.AddKeyPerFile(directoryPath: path, optional: true);
})

内存配置提供程序Memory Configuration Provider

MemoryConfigurationProvider 使用内存中集合作为配置键值对。

若要激活内存中集合配置,请在 ConfigurationBuilder 的实例上调用 AddInMemoryCollection 扩展方法。

可以使用 IEnumerable<KeyValuePair<String,String>> 初始化配置提供程序。

构建主机时调用 ConfigureAppConfiguration 以指定应用的配置。

在下面的示例中,创建了配置字典:

public static readonly Dictionary<string, string> _dict = 
    new Dictionary<string, string>
    {
        {"MemoryCollectionKey1", "value1"},
        {"MemoryCollectionKey2", "value2"}
    };

通过 AddInMemoryCollection 的调用使用字典,以提供配置:

.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.AddInMemoryCollection(_dict);
})

GetValueGetValue

ConfigurationBinder.GetValue<T> 从配置中提取一个具有指定键的值,并将它转换为指定的非集合类型。重载接受默认值。

如下示例中:

  • 使用键 NumberKey 从配置中提取字符串值。如果在配置键中找不到 NumberKey,则使用默认值 99
  • 键入值作为 int
  • 存储 NumberConfig 属性中的值,以供页面使用。
public class IndexModel : PageModel
{
    public IndexModel(IConfiguration config)
    {
        _config = config;
    }

    public int NumberConfig { get; private set; }

    public void OnGet()
    {
        NumberConfig = _config.GetValue<int>("NumberKey", 99);
    }
}

GetSection、GetChildren 和 ExistsGetSection, GetChildren, and Exists

对于下面的示例,请考虑以下 JSON 文件。在两个节中找到四个键,其中一个包含一对子节:

{
  "section0": {
    "key0": "value",
    "key1": "value"
  },
  "section1": {
    "key0": "value",
    "key1": "value"
  },
  "section2": {
    "subsection0" : {
      "key0": "value",
      "key1": "value"
    },
    "subsection1" : {
      "key0": "value",
      "key1": "value"
    }
  }
}

将文件读入配置时,会创建以下唯一的分层键来保存配置值:

  • section0:key0
  • section0:key1
  • section1:key0
  • section1:key1
  • section2:subsection0:key0
  • section2:subsection0:key1
  • section2:subsection1:key0
  • section2:subsection1:key1

GetSectionGetSection

IConfiguration.GetSection 使用指定的子节键提取配置子节。

若要返回仅包含 section1 中键值对的 IConfigurationSection,请调用 GetSection 并提供节名称:

var configSection = _config.GetSection("section1");

configSection 不具有值,只有密钥和路径。

同样,若要获取 section2:subsection0 中键的值,请调用 GetSection 并提供节路径:

var configSection = _config.GetSection("section2:subsection0");

GetSection 永远不会返回 null如果找不到匹配的节,则返回空 IConfigurationSection

GetSection 返回匹配的部分时,Value 未填充。存在该部分时,返回一个 KeyPath 部分。

GetChildrenGetChildren

section2 上调用 IConfiguration.GetChildren 会获得 IEnumerable<IConfigurationSection>,其中包括:

  • subsection0
  • subsection1
var configSection = _config.GetSection("section2");

var children = configSection.GetChildren();

存在Exists

使用 ConfigurationExtensions.Exists 确定配置节是否存在:

var sectionExists = _config.GetSection("section2:subsection2").Exists();

给定示例数据,sectionExistsfalse,因为配置数据中没有 section2:subsection2 节。

绑定至对象图Bind to an object graph

Bind 能够绑定整个 POCO 对象图。与绑定简单对象一样,只绑定公共读取/写入属性。

该示例包含 TvShow 模型,其对象图包含 MetadataActors 类 (Models/TvShow.cs ):

public class TvShow
{
    public Metadata Metadata { get; set; }
    public Actors Actors { get; set; }
    public string Legal { get; set; }
}

public class Metadata
{
    public string Series { get; set; }
    public string Title { get; set; }
    public DateTime AirDate { get; set; }
    public int Episodes { get; set; }
}

public class Actors
{
    public string Names { get; set; }
}

示例应用有一个包含配置数据的 tvshow.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <tvshow>
    <metadata>
      <series>Dr. Who</series>
      <title>The Sun Makers</title>
      <airdate>11/26/1977</airdate>
      <episodes>4</episodes>
    </metadata>
    <actors>
      <names>Tom Baker, Louise Jameson, John Leeson</names>
    </actors>
    <legal>(c)1977 BBC https://www.bbc.co.uk/programmes/b006q2x0</legal>
  </tvshow>
</configuration>

使用 Bind 方法将配置绑定到整个 TvShow 对象图。将绑定实例分配给用于呈现的属性:

var tvShow = new TvShow();
_config.GetSection("tvshow").Bind(tvShow);
TvShow = tvShow;

ConfigurationBinder.Get<T> 绑定并返回指定的类型。Get<T> 比使用 Bind 更方便。以下代码演示了如何通过前述示例使用 Get<T>

TvShow = _config.GetSection("tvshow").Get<TvShow>();

将数组绑定至类Bind an array to a class

示例应用演示了本部分中介绍的概念。

Bind 支持使用配置键中的数组索引将数组绑定到对象。公开数字键段(:0::1:、… :{n}:)的任何数组格式都能够与 POCO 类数组进行数组绑定。

备注

绑定是按约定提供的。不需要自定义配置提供程序实现数组绑定。

内存中数组处理

请考虑下表中所示的配置键和值。

“值”
array:entries:0value0
array:entries:1value1
array:entries:2value2
array:entries:4value4
array:entries:5value5

使用内存配置提供程序在示例应用中加载这些键和值:

public class Program
{
    public static Dictionary<string, string> arrayDict = 
        new Dictionary<string, string>
        {
            {"array:entries:0", "value0"},
            {"array:entries:1", "value1"},
            {"array:entries:2", "value2"},
            {"array:entries:4", "value4"},
            {"array:entries:5", "value5"}
        };

    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddInMemoryCollection(arrayDict);
                config.AddJsonFile(
                    "json_array.json", optional: false, reloadOnChange: false);
                config.AddJsonFile(
                    "starship.json", optional: false, reloadOnChange: false);
                config.AddXmlFile(
                    "tvshow.xml", optional: false, reloadOnChange: false);
                config.AddEFConfiguration(
                    options => options.UseInMemoryDatabase("InMemoryDb"));
                config.AddCommandLine(args);
            })
            .UseStartup<Startup>();
}

该数组跳过索引 #3 的值。配置绑定程序无法绑定 null 值,也无法在绑定对象中创建 null 条目,这在演示将此数组绑定到对象的结果时变得清晰。

在示例应用中,POCO 类可用于保存绑定的配置数据:

public class ArrayExample
{
    public string[] Entries { get; set; }
}

将配置数据绑定至对象:

var arrayExample = new ArrayExample();
_config.GetSection("array").Bind(arrayExample);

还可以使用 ConfigurationBinder.Get<T> 语法,这样会得到更精简的代码:

ArrayExample = _config.GetSection("array").Get<ArrayExample>();

绑定对象(ArrayExample 的实例)从配置接收数组数据。

ArrayExample.Entries 索引ArrayExample.Entries
0value0
1value1
2value2
3value4
4value5

绑定对象中的索引 #3 保留 array:4 配置键的配置数据及其值 value4当绑定包含数组的配置数据时,配置键中的数组索引仅用于在创建对象时迭代配置数据。无法在配置数据中保留 null 值,并且当配置键中的数组跳过一个或多个索引时,不会在绑定对象中创建 null 值条目。

可以在由任何在配置中生成正确键值对的配置提供程序绑定到 ArrayExample 实例之前提供索引 #3 的缺失配置项。如果示例包含具有缺失键值对的其他 JSON 配置提供程序,则 ArrayExample.Entries 与完整配置数组相匹配:

missing_value.json:

{
  "array:entries:3": "value3"
}

ConfigureAppConfiguration中:

config.AddJsonFile(
    "missing_value.json", optional: false, reloadOnChange: false);

将表中所示的键值对加载到配置中。

“值”
array:entries:3value3

如果在 JSON 配置提供程序包含索引 #3 的条目之后绑定 ArrayExample 类实例,则 ArrayExample.Entries 数组包含该值。

ArrayExample.Entries 索引ArrayExample.Entries
0value0
1value1
2value2
3value3
4value4
5value5

JSON 数组处理

如果 JSON 文件包含数组,则会为具有从零开始的节索引的数组元素创建配置键。在以下配置文件中,subsection 是一个数组:

{
  "json_array": {
    "key": "valueA",
    "subsection": [
      "valueB",
      "valueC",
      "valueD"
    ]
  }
}

JSON 配置提供程序将配置数据读入以下键值对:

“值”
json_array:keyvalueA
json_array:subsection:0valueB
json_array:subsection:1valueC
json_array:subsection:2valueD

在示例应用中,以下 POCO 类可用于绑定配置键值对:

public class JsonArrayExample
{
    public string Key { get; set; }
    public string[] Subsection { get; set; }
}

绑定后,JsonArrayExample.Key 保存值 valueA子节值存储在 POCO 数组属性 Subsection 中。

JsonArrayExample.Subsection 索引JsonArrayExample.Subsection
0valueB
1valueC
2valueD

自定义配置提供程序Custom configuration provider

该示例应用演示了如何使用实体框架 (EF) 创建从数据库读取配置键值对的基本配置提供程序。

提供程序具有以下特征:

  • EF 内存中数据库用于演示目的。若要使用需要连接字符串的数据库,请实现辅助 ConfigurationBuilder 以从另一个配置提供程序提供连接字符串。
  • 提供程序在启动时将数据库表读入配置。提供程序不会基于每个键查询数据库。
  • 未实现更改时重载,因此在应用启动后更新数据库对应用的配置没有任何影响。

定义用于在数据库中存储配置值的 EFConfigurationValue 实体。

Models/EFConfigurationValue.cs

public class EFConfigurationValue
{
    public string Id { get; set; }
    public string Value { get; set; }
}

添加 EFConfigurationContext 以存储和访问配置的值。

EFConfigurationProvider/EFConfigurationContext.cs

public class EFConfigurationContext : DbContext
{
    public EFConfigurationContext(DbContextOptions options) : base(options)
    {
    }

    public DbSet<EFConfigurationValue> Values { get; set; }
}

创建用于实现 IConfigurationSource 的类。

EFConfigurationProvider/EFConfigurationSource.cs

public class EFConfigurationSource : IConfigurationSource
{
    private readonly Action<DbContextOptionsBuilder> _optionsAction;

    public EFConfigurationSource(Action<DbContextOptionsBuilder> optionsAction)
    {
        _optionsAction = optionsAction;
    }

    public IConfigurationProvider Build(IConfigurationBuilder builder)
    {
        return new EFConfigurationProvider(_optionsAction);
    }
}

通过从 ConfigurationProvider 继承来创建自定义配置提供程序。当数据库为空时,配置提供程序将对其进行初始化。

EFConfigurationProvider/EFConfigurationProvider.cs

public class EFConfigurationProvider : ConfigurationProvider
{
    public EFConfigurationProvider(Action<DbContextOptionsBuilder> optionsAction)
    {
        OptionsAction = optionsAction;
    }

    Action<DbContextOptionsBuilder> OptionsAction { get; }

    // Load config data from EF DB.
    public override void Load()
    {
        var builder = new DbContextOptionsBuilder<EFConfigurationContext>();

        OptionsAction(builder);

        using (var dbContext = new EFConfigurationContext(builder.Options))
        {
            dbContext.Database.EnsureCreated();

            Data = !dbContext.Values.Any()
                ? CreateAndSaveDefaultValues(dbContext)
                : dbContext.Values.ToDictionary(c => c.Id, c => c.Value);
        }
    }

    private static IDictionary<string, string> CreateAndSaveDefaultValues(
        EFConfigurationContext dbContext)
    {
        // Quotes (c)2005 Universal Pictures: Serenity
        // https://www.uphe.com/movies/serenity
        var configValues = 
            new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
            {
                { "quote1", "I aim to misbehave." },
                { "quote2", "I swallowed a bug." },
                { "quote3", "You can't stop the signal, Mal." }
            };

        dbContext.Values.AddRange(configValues
            .Select(kvp => new EFConfigurationValue 
                {
                    Id = kvp.Key,
                    Value = kvp.Value
                })
            .ToArray());

        dbContext.SaveChanges();

        return configValues;
    }
}

可以使用 AddEFConfiguration 扩展方法将配置源添加到 ConfigurationBuilder

Extensions/EntityFrameworkExtensions.cs :

public static class EntityFrameworkExtensions
{
    public static IConfigurationBuilder AddEFConfiguration(
        this IConfigurationBuilder builder, 
        Action<DbContextOptionsBuilder> optionsAction)
    {
        return builder.Add(new EFConfigurationSource(optionsAction));
    }
}

下面的代码演示如何在 Program.cs 中使用自定义的 EFConfigurationProvider

public class Program
{
    public static Dictionary<string, string> arrayDict = 
        new Dictionary<string, string>
        {
            {"array:entries:0", "value0"},
            {"array:entries:1", "value1"},
            {"array:entries:2", "value2"},
            {"array:entries:4", "value4"},
            {"array:entries:5", "value5"}
        };

    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddInMemoryCollection(arrayDict);
                config.AddJsonFile(
                    "json_array.json", optional: false, reloadOnChange: false);
                config.AddJsonFile(
                    "starship.json", optional: false, reloadOnChange: false);
                config.AddXmlFile(
                    "tvshow.xml", optional: false, reloadOnChange: false);
                config.AddEFConfiguration(
                    options => options.UseInMemoryDatabase("InMemoryDb"));
                config.AddCommandLine(args);
            })
            .UseStartup<Startup>();
}

在启动期间访问配置Access configuration during startup

IConfiguration 注入 Startup 构造函数以访问 Startup.ConfigureServices 中的配置值。若要访问 Startup.Configure 中的配置,请将 IConfiguration 直接注入方法或使用构造函数中的实例:

public class Startup
{
    private readonly IConfiguration _config;

    public Startup(IConfiguration config)
    {
        _config = config;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        var value = _config["key"];
    }

    public void Configure(IApplicationBuilder app, IConfiguration config)
    {
        var value = config["key"];
    }
}

有关使用启动便捷方法访问配置的示例,请参阅应用启动:便捷方法

在 Razor Pages 页或 MVC 视图中访问配置Access configuration in a Razor Pages page or MVC view

若要访问 Razor Pages 页或 MVC 视图中的配置设置,请为 Microsoft.Extensions.Configuration 命名空间添加 using 指令C# 参考:using 指令)并将 IConfiguration 注入页面或视图。

在 Razor 页面页中:

@page
@model IndexModel
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Index Page</title>
</head>
<body>
    <h1>Access configuration in a Razor Pages page</h1>
    <p>Configuration value for 'key': @Configuration["key"]</p>
</body>
</html>

在 MVC 视图中:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Index View</title>
</head>
<body>
    <h1>Access configuration in an MVC view</h1>
    <p>Configuration value for 'key': @Configuration["key"]</p>
</body>
</html>

从外部程序集添加配置Add configuration from an external assembly

通过 IHostingStartup 实现,可在启动时从应用 Startup 类之外的外部程序集向应用添加增强功能。有关详细信息,请参阅 在 ASP.NET Core 中使用承载启动程序集

其他资源Additional resources