编程语言
首页 > 编程语言> > 翻译 - ASP.NET Core 基本知识 - 配置(Configuration)

翻译 - ASP.NET Core 基本知识 - 配置(Configuration)

作者:互联网

翻译自 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-5.0

ASP.NET Core 中的配置使用一个或者多个配置提供程(configuration providers)序实现。配置提供程序从多种键值对中的配置源中读取配置数据:

本话题提供 ASP.NET Core 中关于配置的信息。更多关于在控制台应用程序中使用配置的信息,查看 .NET Configuration.

默认配置

返利网站 www.cpa5.cn

使用 dotnet new 或者 Visual Studio 创建的 ASP.NET Core web 应用程序生成以下代码:

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 按照以下顺序为应用程序提供默认配置:

  1. ChainedConfigurationProvider:添加一个现存的 IConfiguration 作为一个源。在一个默认配置例子中,添加主机(host)配置并且设置它作为第一个应用程序配置的源。
  2. appsettings.json 使用 JSON 配置提供器(JSON configuration provider)。
  3. appsetttings.Environment.json 使用 JSON 配置提供器(JSON configuration provider)。例如,appsettings.Production.json 和 appsettings.Developments.json。
  4. App secrets,当应用程序运行在开发 (Development) 环境中。
  5. 环境变量使用  Environment Variables configuration provider。
  6. 命令行参数使用 Command-line configuration provider。

后添加的配置提供器会覆盖先前添加的键值设置。例如,如果 MyKey 同事在 appsettings.json 和 环境变量中设置,环境变量的值将会被使用。如果使用默认的配置提供器,命令行配置提供器(Command-line configuration provider) 将会覆盖所有的提供器。

关于 CreateDefaultBuilder 的更多信息,查看 Default builder settings。

下面的代码展示了使能的配置提供器的添加顺序:

public class Index2Model : PageModel
{
    private IConfigurationRoot ConfigRoot;

    public Index2Model(IConfiguration configRoot)
    {
        ConfigRoot = (IConfigurationRoot)configRoot;
    }

    public ContentResult OnGet()
    {           
        string str = "";
        foreach (var provider in ConfigRoot.Providers.ToList())
        {
            str += provider.ToString() + "
";
        }

        return Content(str);
    }
}

appsettings.json

考虑下面的 appsettings.json 文件:

{
  "Position": {
    "Title": "Editor",
    "Name": "Joe Smith"
  },
  "MyKey":  "My appsettings.json Value",
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

示例 (sample download) 中的代码展示了几个上面的配置设置:

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} 
" +
                       $"Title: {title} 
" +
                       $"Name: {name} 
" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

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

1. appsettings.json

2. appsettings.Environment.json:例如,appsettings.Production.json 和 appsettings.Development.json 文件。文件的环境版本基于 IHostingEnvironment.EnvironmentName,更多信息,查看 Use multiple environments in ASP.NET Core.

appsettings.Environment.json 中的值会覆盖 appsettings.json 中的值。例如,默认的:

使用选项模型绑定继承配置数据

读取相关配置值的推荐方式是使用选项模型 (options pattern)。例如,读取下面的配置值:

"Position": {
    "Title": "Editor",
    "Name": "Joe Smith"
  }

创建 PositionOptions 类:

public class PositionOptions
{
    public const string Position = "Position";

    public string Title { get; set; }
    public string Name { get; set; }
}

一个选项类:

下面的代码:

public class Test22Model : PageModel
{
    private readonly IConfiguration Configuration;

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

    public ContentResult OnGet()
    {
        var positionOptions = new PositionOptions();
        Configuration.GetSection(PositionOptions.Position).Bind(positionOptions);

        return Content($"Title: {positionOptions.Title} 
" +
                       $"Name: {positionOptions.Name}");
    }
}

在上面的代码中,默认的,在应用程序启动后对于 JSON 配置文件的改变也会被读取到。

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

public class Test21Model : PageModel
{
    private readonly IConfiguration Configuration;
    public PositionOptions positionOptions { get; private set; }

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

    public ContentResult OnGet()
    {            
        positionOptions = Configuration.GetSection(PositionOptions.Position)
                                                     .Get<PositionOptions>();

        return Content($"Title: {positionOptions.Title} 
" +
                       $"Name: {positionOptions.Name}");
    }
}

默认的,上面的代码会读取到在应用程序启动后对于 JSON 配置文件的更改。

使用 options patter 的一种方法是绑定 Position 区域并且添加到依赖注入服务容器 (dependency injection service container) 中。下面的代码中,PositionOptions 在 Configure 中被添加到服务容器中,并绑定到配置:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<PositionOptions>(Configuration.GetSection(
                                        PositionOptions.Position));
    services.AddRazorPages();
}

使用了上面的代码,下面的代码读取 position options:

public class Test2Model : PageModel
{
    private readonly PositionOptions _options;

    public Test2Model(IOptions<PositionOptions> options)
    {
        _options = options.Value;
    }

    public ContentResult OnGet()
    {
        return Content($"Title: {_options.Title} 
" +
                       $"Name: {_options.Name}");
    }
}

上面的代码在应用程序启动后不会读取到对 JSON 配置文件的更改。如果要读取应用程序启动后的更改,可以使用 IOptionsSnapshot。

使用默认(default)的配置,appsettings.json 和 appsettings.Environment.json 文件使能了  reloadOnChange: true 。在应用程序启动后对 appsettings.json 和 appsettings.Environment.json 的更改会被 JSON configuration provider 读取到。

查看本文档中 JSON configuration provider 关于添加更多 JSON 配置文件的信息。

合并服务集合

考虑下面的 ConfigureServices 方法,其中注册服务和配置选项:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<PositionOptions>(
        Configuration.GetSection(PositionOptions.Position));
    services.Configure<ColorOptions>(
        Configuration.GetSection(ColorOptions.Color));

    services.AddScoped<IMyDependency, MyDependency>();
    services.AddScoped<IMyDependency2, MyDependency2>();

    services.AddRazorPages();
}

相关的一组的注册可以被移动到扩展方法中去注册服务。例如,配置服务被添加到下面的类中:

using ConfigSample.Options;
using Microsoft.Extensions.Configuration;

namespace Microsoft.Extensions.DependencyInjection
{
    public static class MyConfigServiceCollectionExtensions
    {
        public static IServiceCollection AddConfig(
             this IServiceCollection services, IConfiguration config)
        {
            services.Configure<PositionOptions>(
                config.GetSection(PositionOptions.Position));
            services.Configure<ColorOptions>(
                config.GetSection(ColorOptions.Color));

            return services;
        }
    }
}

其余的服务在一个相似的类中被注册。下面的 ConfigureServices 方法使用的新的扩展方法注册服务:

public void ConfigureServices(IServiceCollection services)
{
    services.AddConfig(Configuration)
            .AddMyDependencyGroup();

    services.AddRazorPages();
}

备注:每一个 services.Add{GROUP_NAME} 扩展方法添加和潜在的会配置服务。例如,AddControllersWithViews 添加带有视图的 MVC 控制器的服务,AddRazorPages 添加带有 Razor Pages 的服务。我们推荐应用程序遵守命名的约定。把扩展方法统一放到命名空间 Microsoft.Extensions.DependencyInjection 中去封装一组服务的注册。

安全和用户秘密

数据配置指导:

默认的,用户秘密配置源是在 JSON 配置源之后注册的。因此,用户秘密的键值会生效,而不是 appsettings.json 和 appsettings.Environment.json 中的键值。

更多关于存储密码或者其他敏感数据的信息:

Azure Key Vault 为 ASP.NET Core 应用程序安全的存储应用程序的秘密。更多信息查看 Azure Key Vault Configuration Provider in ASP.NET Core。

环境变量

使用默认的配置,EnvironmentVariablesConfigurationProvider 在读取 appsettings.json,appsettings.Environment.json,和 user secrets 之后从环境变量加载键值对。因此,从环境变量读取到的键值会覆盖从 appsettings.json, appsettings.Environment.json 和 user secrets 中读取到的值。

: 分隔符在所有平台上对于环境便令分级键都是不工作的。__ 双下换线:

下面的设置命令:

set MyKey="My key from Environment"
set Position__Title=Environment_Editor
set Position__Name=Environment_Rick
dotnet run

上面的环境变量设置:

下面的  setx 命令可以被用来在 Windows 上设置环境键和值。不同于 set,setx 是持久化的。/M 在系统环境设置变量。如果没有使用 /M 开关,一个用户的环境变量会被设置。

setx MyKey "My key from setx Environment" /M
setx Position__Title Setx_Environment_Editor /M
setx Position__Name Environment_Rick /M

为了测试上面的命令会覆盖 appsettings.json 和 asppsettings.Environment.json 的配置,需要做以下操作:

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

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

在上面的代码中:

当配置键值对被读取的时候,前缀会被去除。

下面的命令测试自定义前缀:

set MyCustomPrefix_MyKey="My key with MyCustomPrefix_ Environment"
set MyCustomPrefix_Position__Title=Editor_with_customPrefix
set MyCustomPrefix_Position__Name=Environment_Rick_cp
dotnet run

默认配置 (default configuration) 加载带有前缀为 DOTNET_ 和 ASPNETCORE_ 的环境变量和命令行参数。DOTNET_ 和 ASPNETCORE_ 前缀被 ASP.NET Core 用来配置主机和应用程序配置 (host and app configuration),不能用来作为用户配置。更多关于主机和应用程序的配置,查看 .NET Generic Host。

关于  Azure App Service,在设置 (Settings) > 配置 (Configuration) 页面选择 新建应用程序设置 (New application setting)。Azure 应用程序服务设置:

更多信息,查看 Azure Apps: Override app configuration using the Azure Portal。

查看 Connection string prefixes 了解关于 Azure 数据库连接字符串的信息。

 环境变量命名

环境变量的命名反映了 appsettings.json 文件的结构。层级中的每一个元素使用双下划线(推荐的)或者冒号分割开来。当一个元素的结构包含一个数组的时候,数组的索引应该被当做是当前路径中的一个额外的元素名称。考虑下面的 appsettings.json 文件和它在环境变量中等价的值。

appsettings.json

{
    "SmtpServer": "smtp.example.com",
    "Logging": [
        {
            "Name": "ToEmail",
            "Level": "Critical",
            "Args": {
                "FromAddress": "MySystem@example.com",
                "ToAddress": "SRE@example.com"
            }
        },
        {
            "Name": "ToConsole",
            "Level": "Information"
        }
    ]
}

环境变量 (environment variables)

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

生成的 launchSettings.json 文件中环境变量的设置

在 launchSettings.json 中设置的环境变量会覆盖那些在系统环境中设置的值。例如,ASP.NET Core web 模板会生成一个 lauchSettings.json 文件,文件中设置了

endpoint 配置:

"applicationUrl": "https://localhost:5001;http://localhost:5000"

对 applicationUrl 的配置设置环境变量 ASPNETCORE_URLS  并覆盖环境中的值。

Escape environment variables on Linux

在 linux 上,URL 环境变量的值必须被 escape 后系统才能够解析它。使用 linux systemd-escape 工具生成 http:--localhost:5001

groot@terminus:~$ systemd-escape http://localhost:5001
http:--localhost:5001

显示环境变量

下面的代码在应用程序启动的时候输出显示了环境变量和对应的值,在调试环境设置的时候非常有用:

public static void Main(string[] args)
{
    var host = CreateHostBuilder(args).Build();

    var config = host.Services.GetRequiredService<IConfiguration>();

    foreach (var c in config.AsEnumerable())
    {
        Console.WriteLine(c.Key + " = " + c.Value);
    }
    host.Run();
}

命令行

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

默认的,在命令行中配置的值会覆盖其它所有配置提供的值。

命令行参数

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

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

键值:

在相同的命令行中,不要把使用 = 的键值对和使用空格的键值对的命令行参数混淆。

转换映射

切换映射允许键名替换逻辑。可以给 AddCommandLine 方法提供一个切换替换的字典。

当切换映射字典被用到的时候,字典被用来检查匹配命令行参数提供的键。日过命令行的键在字典中被找到,字典中的值就会被传回用来设置应用程序配置的键值对。切换映射要求任何的命令行键使用一个单独的破折号作为前缀。

切换映射字典键的规则:

 

使用一个切换映射字典,需要把它传递给 AddCommandLine 方法:

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

    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        var switchMappings = new Dictionary<string, string>()
         {
             { "-k1", "key1" },
             { "-k2", "key2" },
             { "--alt3", "key3" },
             { "--alt4", "key4" },
             { "--alt5", "key5" },
             { "--alt6", "key6" },
         };

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

下面的代码展示了被替换的键的值:

public class Test3Model : PageModel
{
    private readonly IConfiguration Config;

    public Test3Model(IConfiguration configuration)
    {
        Config = configuration;
    }

    public ContentResult OnGet()
    {
        return Content(
                $"Key1: '{Config["Key1"]}'
" +
                $"Key2: '{Config["Key2"]}'
" +
                $"Key3: '{Config["Key3"]}'
" +
                $"Key4: '{Config["Key4"]}'
" +
                $"Key5: '{Config["Key5"]}'
" +
                $"Key6: '{Config["Key6"]}'");
    }
}

下面的命令用来测试键替换:

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

对于使用切换映射的应用程序,调用 CreateDefaultBuilder 不应该传递参数。CreateDefaultBuilder 方法的 AddCommandLine 的调用不包括映射切换,没有方法可以传递切换映射的字典给 CreateDefaultBuilder。解决方法是允许 ConfigurationBuilder 方法的 AddCommandLine 同时处理参数和切换映射字典而不是传递参数给 CreateDefaultBuilder。

分层配置数据

配置 API 通过使用在配置键中的分界符扁平化分层数据来读取配置数据。

示例程序 (sample download) 包含下面的 appsettings.json 文件:

{
  "Position": {
    "Title": "Editor",
    "Name": "Joe Smith"
  },
  "MyKey":  "My appsettings.json Value",
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

下面示例 (sample download) 中的代码展示了一些配置设置:

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} 
" +
                       $"Title: {title} 
" +
                       $"Name: {name} 
" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

读取分层配置数据的首选方式是使用选项模型。更多信息,查看本文档中的绑定分层配置数据 (Bind hierarchical configuration data)。

GetSection 和 GetChildren 方法可以用来分离配置数据中的分区和分区中的子部分。这些方法在之后的 GetSection, GetChildren, and Exists 中会描述到。

配置的键和值

配置的键:

配置值:

配置提供器

下面的表格中显示了 ASP.NET Core 应用程序中可以使用的配置提供器

ProviderProviders configuration from
Azure Key Vault configuration providerAzure Key Valut
Azure App configuration providerAzure App Configuration
Command-line configuration providerCommand-line parameters
Custom configuration providerCustom source
Environment Variables configuration providerEnvironment variables
File configuration providerINI,JSON,XML 文件
Key-per-file configuration provider字典文件
Memory configuration provider内存中的集合
User secrets用户配置目录中的文件

配置源的读取的顺序按照它们的配置提供器被指定的顺序。在代码中对配置提供器排序来满足应用程序要求的配置源的顺序。

一个典型的配置提供器的顺序是:

  1. appsettings.json
  2. appsettings.Environment.json
  3. User secrets
  4. 使用 Environment Variables configuration provider 的环境变量
  5. 使用 Command-line configuration provider 的命令行参数

一个常用的实践是在一系列的配置提供器的最后添加命令行配置提供器,用来覆盖其它提供器的配置设置

上面的提供器的顺序在默认配置 (default configuration) 中使用。

连接字符串前缀

配置 API 对于四种连接字符串环境变量有特殊的处理规则。这些连接字符串会根据应用程序环境解析来配置 Azure 连接字符串。下面表格中的带有前缀的环境变量在应用程序使用默认配置 (default configuration)或者没有前缀没有应用到 AddEnvironmentVariables 的情况下会被加载到应用程序中。

Connection string prefixProvider
CUSTOMCONNSTR_自定义提供器
MYSQLCONNSTR_MySQL
SQLAZURECONNSTR_Azure SQL Database
SQLCONNSTR_SQL Server

当一个环境变量被发现并且使用表格中四种前缀的任一种被加载到配置中的时候:

环境变量键转换后的配置键提供器配置入口
CUSTOMCONNSTR_{KEY}ConnectionStrings:{KEY}配置入口没有创建
MYSQLCONNSTR_{KEY}ConnectionString:{KEY}

Key:ConnectionStrings:

{KEY}_ProviderName:

Value:MySql.DataMySqlClient

SQLAZURECONNSTR_{KEY}ConnectionStrings:{KEY}

Key:ConnectionStrings:

{KEY}_ProviderName:

Value:System.Data.SqlClient

SQLCONNSTR_{KEY}ConnectionStrings:{KEY}

Key:ConnectionStrings:

{KEY}_ProviderName:

Value:System.Data.SqlClient

 文件配置提供器

FileConfigurationProvider 是从文件系统加载配置的基类。下面的配置提供器都从 FileConfigurationProvider 类继承而来。

INI 配置提供器

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

下面的代码清空了所有配置提供器,添加了一些配置提供器:

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

 

标签:Core,ASP,appsettings,配置,json,Position,NET,configuration,public
来源: https://blog.csdn.net/weixin_48967543/article/details/115254489