ASP.NET Core 2.2 基礎知識(六)【Configuration】

風靈使發表於2019-02-19

ASP.NET Core 中的應用配置基於配置提供程式建立的鍵值對。 配置提供程式將配置資料從各種配置源讀取到鍵值對:

  • Azure Key Vault
  • 命令列引數
  • (已安裝或已建立的)自定義提供程式
  • 目錄檔案
  • 環境變數
  • 記憶體中的 .NET 物件
  • 設定檔案

選項模式是本主題中描述的配置概念的擴充套件。 選項使用類來表示相關設定的組。 有關使用選項模式的詳細資訊,請參閱 ASP.NET Core 中的選項模式

這三個包均包括在 Microsoft.AspNetCore.App 元包中。

主機與應用配置

在配置並啟動應用之前,配置並啟動主機。 主機負責應用程式啟動和生存期管理。 應用和主機均使用本主題中所述的配置提供程式進行配置。 主機配置鍵值對成為應用的全域性配置的一部分。 有關在構建主機時如何使用配置提供程式以及配置源如何影響主機配置的詳細資訊,請參閱 ASP.NET Core 中的 Web 主機和通用主機

預設配置

基於 ASP.NET Core dotnet new模板的 Web 應用在生成主機時會呼叫 CreateDefaultBuilderCreateDefaultBuilder 為應用提供預設配置。

  • 主機配置通過以下方式提供:
    • 使用環境變數配置提供程式,通過字首為 ASPNETCORE_(例如,ASPNETCORE_ENVIRONMENT)的環境變數提供。
    • 使用命令列配置提供程式,通過命令列引數提供。
  • 應用配置通過以下方式提供(按以下順序):
    • 使用檔案配置提供程式,通過 appsettings.json 提供。
    • 使用檔案配置提供程式,通過 appsettings.{Environment}.json 提供。
    • 應用在使用入口程式集的 Development 環境中執行時的機密管理器
    • 使用環境變數配置提供程式,通過環境變數提供。
    • 使用命令列配置提供程式,通過命令列引數提供。

本主題後面將介紹配置提供程式。 有關主機和 CreateDefaultBuilder 的更多資訊,請參閱 ASP.NET Core Web 主機

安全性

採用以下最佳實踐:

  • 請勿在配置提供程式程式碼或純文字配置檔案中儲存密碼或其他敏感資料。
  • 不要在開發或測試環境中使用生產機密。
  • 請在專案外部指定機密,避免將其意外提交到原始碼儲存庫。

詳細瞭解如何使用多個環境和管理使用 Secret Manager 的開發中的應用機密的安全儲存(包括使用環境變數儲存敏感資料的建議)。 Secret Manager 使用檔案配置提供程式將使用者機密儲存在本地系統上的 JSON 檔案中。 本主題後面將介紹檔案配置提供程式。

Azure Key Vault 是安全儲存應用機密的一種選擇。 有關更多資訊,請參見在 ASP.NET Core 中的 azure 金鑰保管庫配置提供程式

分層配置資料

配置 API 能夠通過在配置鍵中使用分隔符來展平分層資料以保持分層配置資料。

在以下 JSON 檔案中,兩個節的結構化層次結構中存在四個鍵:

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

將檔案讀入配置時,將建立唯一鍵以保持配置源的原始分層資料結構。 使用冒號 (:) 展平節和鍵以保持原始結構:

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

GetSectionGetChildren方法可用於隔離各個節和配置資料中某節的子節。 稍後將在GetSection、GetChildren 和 Exists 中介紹這些方法。GetSectionMicrosoft.Extensions.Configuration 包中,後者在 Microsoft.AspNetCore.App 元包中。

約定

在應用啟動時,將按照指定的配置提供程式的順序讀取配置源。

應用啟動後,在更改基礎設定檔案時,檔案配置提供程式可以過載配置。 本主題後面將介紹檔案配置提供程式。

應用的依賴關係注入 (DI)容器中提供了IConfiguration。配置提供程式不能使用 DI,因為主機在設定這些提供程式時 DI 不可用。

配置鍵採用以下約定:

  • 鍵不區分大小寫。 例如,ConnectionStringconnectionstring 被視為等效鍵。
  • 如果由相同或不同的配置提供程式設定相同鍵的值,則鍵上設定的最後一個值就是所使用的值。
  • 分層鍵
    • 在配置 API 中,冒號分隔符 (:) 適用於所有平臺。
    • 在環境變數中,冒號分隔符可能無法適用於所有平臺。 而所有平臺均支援採用雙下劃線 (__),並可以將其轉換為冒號。
    • 在 Azure Key Vault 中,分層鍵使用 --(兩個破折號)作為分隔符。 將機密載入到應用的配置中時,必須提供程式碼以用冒號替換破折號。
  • ConfigurationBinder 支援使用配置鍵中的陣列索引將陣列繫結到物件。 陣列繫結將在將陣列繫結到類部分中進行介紹。

配置值採用以下約定:

  • 值是字串。
  • NULL 值不能儲存在配置中或繫結到物件。

提供程式

下表顯示了 ASP.NET Core 應用可用的配置提供程式。

提供程式 通過以下物件提供配置…
Azure Key Vault 配置提供程式(安全主題) Azure Key Vault
命令列配置提供程式 命令列引數
自定義配置提供程式 自定義源
環境變數配置提供程式 環境變數
檔案配置提供程式 檔案(INI、JSON、XML)
Key-per-file 配置提供程式 目錄檔案
記憶體配置提供程式 記憶體中集合
使用者機密 (Secret Manager)(安全主題) 使用者配置檔案目錄中的檔案

按照啟動時指定的配置提供程式的順序讀取配置源。 本主題中所述的配置提供程式按字母順序進行介紹,而不是按程式碼排列順序進行介紹。 程式碼中的配置提供程式應以特定順序排列以符合基礎配置源的優先順序。

配置提供程式的典型順序為:

  1. 檔案(appsettings.json、appsettings.{Environment}.json,其中 {Environment} 是應用的當前託管環境)
  2. Azure 金鑰保管庫
  3. 使用者機密 (Secret Manager)(僅限開發環境中)
  4. 環境變數
  5. 命令列引數

通常的做法是將命令列配置提供程式置於一系列提供程式的末尾,以允許命令列引數替代由其他提供程式設定的配置。

在使用 CreateDefaultBuilder初始化新的 WebHostBuilder時,將使用此提供程式序列。 有關詳細資訊,請參閱Web 主機:設定主機

ConfigureAppConfiguration

構建主機時呼叫 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.SetBasePath(Directory.GetCurrentDirectory());
                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>();
}

命令列配置提供程式

CommandLineConfigurationProvider在執行時從命令列引數鍵值對載入配置。

要啟用命令列配置,請在 ConfigurationBuilder的例項上呼叫 AddCommandLine擴充套件方法。

使用 CreateDefaultBuilder初始化新的WebHostBuilder時會自動呼叫 AddCommandLine。 有關詳細資訊,請參閱Web 主機:設定主機

此外,CreateDefaultBuilder 也會載入:

  • appsettings.jsonappsettings.{Environment}.json 的可選配置。
  • 使用者機密 (Secret Manager)(在開發環境中)。
  • 環境變數。

CreateDefaultBuilder 最後新增命令列配置提供程式。 在執行時傳遞的命令列引數會替代由其他提供程式設定的配置。

CreateDefaultBuilder 在構造主機時起作用。 因此,CreateDefaultBuilder 啟用的命令列配置可能會影響主機的配置方式。

構建主機時呼叫 ConfigureAppConfiguration 以指定應用的配置。

CreateDefaultBuilder 已經呼叫了 AddCommandLine。 如果需要提供應用配置並仍然能夠使用命令列引數覆蓋該配置,請在ConfigureAppConfiguration 中呼叫應用的其他提供程式並最後呼叫 AddCommandLine

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

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                // Call other providers here and call AddCommandLine last.
                config.AddCommandLine(args);
            })
            .UseStartup<Startup>();
}

直接建立 WebHostBuilder時,請使用以下配置呼叫UseConfiguration

var config = new ConfigurationBuilder()
    // Call additional providers here as needed.
    // Call AddCommandLine last to allow arguments to override other configuration.
    .AddCommandLine(args)
    .Build();

var host = new WebHostBuilder()
    .UseConfiguration(config)
    .UseKestrel()
    .UseStartup<Startup>();

示例

2.x 示例應用利用靜態便捷方法 CreateDefaultBuilder 來構建主機,其中包括對 AddCommandLine的呼叫。

  1. 在專案的目錄中開啟命令提示符。
  2. dotnet run 命令提供命令列引數 dotnet run CommandLineKey=CommandLineValue
  3. 應用執行後,在 http://localhost:5000 開啟應用的瀏覽器。
  4. 觀察輸出是否包含提供給 dotnet run 的配置命令列引數的鍵值對。

自變數

該值必須後跟一個等號 (=),否則當值後跟一個空格時,鍵必須具有字首(--/)。 如果使用等號(例如,CommandLineKey=),則該值可以為 null

鍵字首 示例
無字首 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

交換對映

交換對映支援鍵名替換邏輯。 使用ConfigurationBuilder手動構建配置時,可以為 AddCommandLine 方法提供交換替換字典。

當使用交換對映字典時,會檢查字典中是否有與命令列引數提供的鍵匹配的鍵。 如果在字典中找到命令列鍵,則傳回字典值(鍵替換)以將鍵值對設定為應用的配置。 對任何具有單劃線 (-) 字首的命令列鍵而言,交換對映都是必需的。

交換對映字典鍵規則:

  • 交換必須以單劃線 (-) 或雙劃線 (--) 開頭。
  • 交換對映字典不得包含重複鍵。

構建主機時呼叫 ConfigureAppConfiguration以指定應用的配置:

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

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

    // Do not pass the args to CreateDefaultBuilder
    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder()
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddCommandLine(args, _switchMappings);
            })
            .UseStartup<Startup>();
}

如前面的示例所示,當使用交換對映時,對 CreateDefaultBuilder 的呼叫不應傳遞引數。 CreateDefaultBuilder 方法的 AddCommandLine 呼叫不包括對映的交換,並且無法將交換對映字典傳遞給 CreateDefaultBuilder。 如果引數包含對映的交換並傳遞給 CreateDefaultBuilder,則其 AddCommandLine 提供程式無法使用 FormatException 進行初始化。 解決方案不是將引數傳遞給 CreateDefaultBuilder,而是允許 ConfigurationBuilder 方法的 AddCommandLine 方法處理引數和交換對映字典。

建立交換對映字典後,它將包含下表所示的資料。

-CLKey1 CommandLineKey1
-CLKey2 CommandLineKey2

如果在啟動應用時使用了交換對映的鍵,則配置將接收字典提供的金鑰上的配置值:

dotnet run -CLKey1=value1 -CLKey2=value2

執行上述命令後,配置包含下表中顯示的值。

CommandLineKey1 value1
CommandLineKey2 value2

環境變數配置提供程式

EnvironmentVariablesConfigurationProvider在執行時從環境變數鍵值對載入配置。

要啟用環境變數配置,請在 ConfigurationBuilder 的例項上呼叫AddEnvironmentVariables擴充套件方法。

在環境變數中使用分層鍵時,冒號分隔符 (:) 可能無法適用於所有平臺。 所有平臺均支援採用雙下劃線 (__),並可以用冒號替換。

藉助 Azure 應用服務,使用者可以在 Azure 門戶中設定使用環境變數配置提供程式替代應用配置的環境變數。 有關詳細資訊,請參閱Azure 應用:使用 Azure 門戶替代應用配置

初始化一個新的 WebHostBuilder時,對於字首為 ASPNETCORE_ 的環境變數,會自動呼叫 AddEnvironmentVariables。 有關詳細資訊,請參閱 Web 主機:設定主機

此外,CreateDefaultBuilder 也會載入:

  • 來自沒有字首的環境變數的應用配置,方法是通過呼叫不帶字首的 AddEnvironmentVariables
  • appsettings.json 和 appsettings.{Environment}.json 的可選配置。
  • 使用者機密 (Secret Manager)(在開發環境中)。
  • 命令列引數。

環境變數配置提供程式是在配置已根據使用者機密和 appsettings 檔案建立後呼叫。 在此位置呼叫提供程式允許在執行時讀取的環境變數替代由使用者機密和 appsettings 檔案設定的配置。

構建主機時呼叫ConfigureAppConfiguration以指定應用的配置。

如果需要從其他環境變數提供應用配置,請在ConfigureAppConfiguration中呼叫應用的其他提供程式,並使用字首呼叫 AddEnvironmentVariables

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

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                // Call additional providers here as needed.
                // Call AddEnvironmentVariables last if you need to allow environment
                // variables to override values from other providers.
                config.AddEnvironmentVariables(prefix: "PREFIX_");
            })
            .UseStartup<Startup>();
}

直接建立 WebHostBuilder 時,請使用以下配置呼叫UseConfiguration

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

var host = new WebHostBuilder()
    .UseConfiguration(config)
    .UseKestrel()
    .UseStartup<Startup>();

示例
2.x 示例應用利用靜態便捷方法 CreateDefaultBuilder 來構建主機,其中包括對 AddEnvironmentVariables 的呼叫。

  1. 執行示例應用。 在 http://localhost:5000 開啟應用的瀏覽器。
  2. 觀察輸出是否包含環境變數 ENVIRONMENT 的鍵值對。 該值反映了應用執行的環境,在本地執行時通常為 Development

為了使應用呈現的環境變數列表簡短,應用將環境變數篩選為以下列內容開頭的變數:

  • ASPNETCORE_
  • urls
  • 日誌記錄
  • ENVIRONMENT
  • contentRoot
  • AllowedHosts
  • applicationName
  • CommandLine

如果希望公開應用可用的所有環境變數,請將 Pages/Index.cshtml.cs 中的 FilteredConfiguration 更改為以下內容:

FilteredConfiguration = _config.AsEnumerable();

字首

AddEnvironmentVariables 方法提供字首時,將篩選載入到應用的配置中的環境變數。 例如,要篩選字首 CUSTOM_ 上的環境變數,請將字首提供給配置提供程式:

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

建立配置鍵值對時,將去除字首。

靜態便捷方法 CreateDefaultBuilder 建立一個WebHostBuilder以建立應用的主機。 建立 WebHostBuilder 時,它會在字首為 ASPNETCORE_ 的環境變數中找到其主機配置。

連線字串字首
針對為應用環境配置 Azure 連線字串所涉及的四個連線字串環境變數,配置 API 具有特殊的處理規則。 如果沒有向 AddEnvironmentVariables 提供字首,則具有表中所示字首的環境變數將載入到應用中。

連線字串字首 提供程式
CUSTOMCONNSTR_ 自定義提供程式
MYSQLCONNSTR_ MySQL
SQLAZURECONNSTR_ Azure SQL 資料庫
SQLCONNSTR_ SQL 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

檔案配置提供程式

FileConfigurationProvider是從檔案系統載入配置的基類。 以下配置提供程式專用於特定檔案型別:

  • INI 配置提供程式
  • JSON 配置提供程式
  • XML 配置提供程式

INI 配置提供程式

IniConfigurationProvider 在執行時從 INI 檔案鍵值對載入配置。

若要啟用 INI 檔案配置,請在 ConfigurationBuilder的例項上呼叫AddIniFile擴充套件方法。

冒號可用作 INI 檔案配置中的節分隔符。

過載允許指定:

  • 檔案是否可選。
  • 如果檔案更改,是否過載配置。
  • IFileProvider用於訪問該檔案。

構建主機時呼叫 ConfigureAppConfiguration以指定應用的配置:

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

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.SetBasePath(Directory.GetCurrentDirectory());
                config.AddIniFile("config.ini", optional: true, reloadOnChange: true);
            })
            .UseStartup<Startup>();
}

基路徑使用 SetBasePath設定。 SetBasePathMicrosoft.Extensions.Configuration.FileExtensions 包中,後者在 Microsoft.AspNetCore.App 元包中。

直接建立 WebHostBuilder 時,請使用以下配置呼叫 UseConfiguration

var config = new ConfigurationBuilder()
    .SetBasePath(Directory.GetCurrentDirectory())
    .AddIniFile("config.ini", optional: true, reloadOnChange: true)
    .Build();

var host = new WebHostBuilder()
    .UseConfiguration(config)
    .UseKestrel()
    .UseStartup<Startup>();

基路徑使用 SetBasePath設定。 SetBasePathMicrosoft.Extensions.Configuration.FileExtensions 包中,後者在 Microsoft.AspNetCore.App 元包中。

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 配置提供程式

JsonConfigurationProvider在執行時期間從 JSON 檔案鍵值對載入配置。

若要啟用 JSON 檔案配置,請在ConfigurationBuilder的例項上呼叫AddJsonFile擴充套件方法。

過載允許指定:

  • 檔案是否可選。
  • 如果檔案更改,是否過載配置。
  • IFileProvider用於訪問該檔案。

使用 CreateDefaultBuilder 初始化新的 WebHostBuilder 時,會自動呼叫 AddJsonFile 兩次。 呼叫該方法來從以下檔案載入配置:

  • appsettings.json – 首先讀取此檔案。 該檔案的環境版本可以替代 appsettings.json 檔案提供的值。
  • appsettings.{Environment}.json– 根據 IHostingEnvironment.EnvironmentName載入檔案的環境版本。

有關詳細資訊,請參閱 Web 主機:設定主機

此外,CreateDefaultBuilder 也會載入:

  • 環境變數。
  • 使用者機密 (Secret Manager)(在開發環境中)。
  • 命令列引數。

首先建立 JSON 配置提供程式。 因此,使用者機密、環境變數和命令列引數會替代由 appsettings 檔案設定的配置。

構建主機時呼叫 ConfigureAppConfiguration以指定除 appsettings.jsonappsettings.{Environment}.json 以外的檔案的應用配置:

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

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.SetBasePath(Directory.GetCurrentDirectory());
                config.AddJsonFile("config.json", optional: true, reloadOnChange: true);
            })
            .UseStartup<Startup>();
}

基路徑使用 SetBasePath設定。 SetBasePathMicrosoft.Extensions.Configuration.FileExtensions 包中,後者在Microsoft.AspNetCore.App 元包中。

直接建立 WebHostBuilder時,請使用以下配置呼叫 UseConfiguration

var config = new ConfigurationBuilder()
    .SetBasePath(Directory.GetCurrentDirectory())
    .AddJsonFile("config.json", optional: true, reloadOnChange: true)
    .Build();

var host = new WebHostBuilder()
    .UseConfiguration(config)
    .UseKestrel()
    .UseStartup<Startup>();

基路徑使用 SetBasePath設定。 SetBasePathMicrosoft.Extensions.Configuration.FileExtensions 包中,後者在 Microsoft.AspNetCore.App 元包中。

示例
2.x 示例應用利用靜態便捷方法 CreateDefaultBuilder 來構建主機,其中包括對 AddJsonFile 的兩次呼叫。 配置從 appsettings.jsonappsettings.{Environment}.json 進行載入。

  1. 執行示例應用。 在 http://localhost:5000 開啟應用的瀏覽器。
  2. 觀察輸出是否包含表中所示的配置的鍵值對,具體取決於環境。 記錄配置鍵使用冒號 (:) 作為分層分隔符。
開發值 生產值
Logging:LogLevel:System 資訊 資訊
Logging:LogLevel:Microsoft 資訊 資訊
Logging:LogLevel:Default 除錯 Error
AllowedHosts * *

XML 配置提供程式

XmlConfigurationProvider在執行時從 XML 檔案鍵值對載入配置。

若要啟用 XML 檔案配置,請在 ConfigurationBuilder的例項上呼叫 AddXmlFile擴充套件方法。

過載允許指定:

  • 檔案是否可選。
  • 如果檔案更改,是否過載配置。
  • IFileProvider用於訪問該檔案。

建立配置鍵值對時,將忽略配置檔案的根節點。 不要在檔案中指定文件型別定義 (DTD) 或名稱空間。

構建主機時呼叫 ConfigureAppConfiguration以指定應用的配置:

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

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.SetBasePath(Directory.GetCurrentDirectory());
                config.AddXmlFile("config.xml", optional: true, reloadOnChange: true);
            })
            .UseStartup<Startup>();
}

基路徑使用 SetBasePath 設定。 SetBasePathMicrosoft.Extensions.Configuration.FileExtensions 包中,後者在Microsoft.AspNetCore.App 元包中。

直接建立 WebHostBuilder時,請使用以下配置呼叫UseConfiguration

var config = new ConfigurationBuilder()
    .SetBasePath(Directory.GetCurrentDirectory())
    .AddXmlFile("config.xml", optional: true, reloadOnChange: true)
    .Build();

var host = new WebHostBuilder()
    .UseConfiguration(config)
    .UseKestrel()
    .UseStartup<Startup>();

基路徑使用 SetBasePath設定。 SetBasePathMicrosoft.Extensions.Configuration.FileExtensions 包中,後者在 Microsoft.AspNetCore.App 元包中。

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?key0
  • section:section0?key1
  • section:section1?key0
  • section:section1?key1

屬性可用於提供值:

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

以前的配置檔案使用 value 載入以下鍵:

  • key:attribute
  • section?attribute

Key-per-file 配置提供程式

KeyPerFileConfigurationProvider使用目錄的檔案作為配置鍵值對。 該鍵是檔名。 該值包含檔案的內容。 Key-per-file 配置提供程式用於 Docker 託管方案。

若要啟用 Key-per-file 配置,請在 ConfigurationBuilder 的例項上呼叫 AddKeyPerFile擴充套件方法。 檔案的 directoryPath 必須是絕對路徑。

過載允許指定:

  • 配置源的 Action<KeyPerFileConfigurationSource> 委託。
  • 目錄是否可選以及目錄的路徑。

雙下劃線字元 (__) 用作檔名中的配置鍵分隔符。 例如,檔名 Logging__LogLevel__System 生成配置鍵 Logging:LogLevel:System

構建主機時呼叫 ConfigureAppConfiguration以指定應用的配置:

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

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.SetBasePath(Directory.GetCurrentDirectory());
                var path = Path.Combine(Directory.GetCurrentDirectory(), "path/to/files");
                config.AddKeyPerFile(directoryPath: path, optional: true);
            })
            .UseStartup<Startup>();
}

基路徑使用 SetBasePath設定。 SetBasePathMicrosoft.Extensions.Configuration.FileExtensions 包中,後者在 Microsoft.AspNetCore.App 元包中。

直接建立 WebHostBuilder時,請使用以下配置呼叫 UseConfiguration

var path = Path.Combine(Directory.GetCurrentDirectory(), "path/to/files");
var config = new ConfigurationBuilder()
    .AddKeyPerFile(directoryPath: path, optional: true)
    .Build();

var host = new WebHostBuilder()
    .UseConfiguration(config)
    .UseKestrel()
    .UseStartup<Startup>();

記憶體配置提供程式

MemoryConfigurationProvider 使用記憶體中集合作為配置鍵值對。

若要啟用記憶體中集合配置,請在 ConfigurationBuilder的例項上呼叫 AddInMemoryCollection擴充套件方法。

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

構建主機時呼叫 ConfigureAppConfiguration以指定應用的配置:

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

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

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddInMemoryCollection(_dict);
            })
            .UseStartup<Startup>();
}

直接建立 WebHostBuilder 時,請使用以下配置呼叫 UseConfiguration

var dict = new Dictionary<string, string>
    {
        {"MemoryCollectionKey1", "value1"},
        {"MemoryCollectionKey2", "value2"}
    };

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

var host = new WebHostBuilder()
    .UseConfiguration(config)
    .UseKestrel()
    .UseStartup<Startup>();

GetValue

ConfigurationBinder.GetValue<T>從具有指定鍵的配置中提取一個值,並將其轉換為指定型別。 如果未找到該鍵,則過載允許你提供預設值。

以下示例使用鍵 NumberKey 從配置中提取字串值,鍵入該值作為 int,並將值儲存在變數 intValue 中。 如果在配置鍵中找不到 NumberKey,則 intValue 會接收 99 的預設值:

var intValue = config.GetValue<int>("NumberKey", 99);

GetSection、GetChildrenExists

對於下面的示例,請考慮以下 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

GetSection

IConfiguration.GetSection使用指定的子節鍵提取配置子節。 GetSectionMicrosoft.Extensions.Configuration 包中,後者在 Microsoft.AspNetCore.App 元包中。

若要返回僅包含 section1 中鍵值對的 IConfigurationSection,請呼叫 GetSection 並提供節名稱:

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

configSection 不具有值,只有金鑰和路徑。

同樣,若要獲取 section2:subsection0 中鍵的值,請呼叫 GetSection 並提供節路徑:

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

GetSection 永遠不會返回 null。 如果找不到匹配的節,則返回空 IConfigurationSection

GetSection 返回匹配的部分時,Value未填充。 存在該部分時,返回一個 KeyPath部分。

GetChildren

section2 上呼叫 IConfiguration.GetChildren 會獲得 IEnumerable<IConfigurationSection>,其中包括:

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

var children = configSection.GetChildren();

存在

使用 ConfigurationExtensions.Exists確定配置節是否存在:

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

給定示例資料,sectionExistsfalse,因為配置資料中沒有 section2:subsection2 節。

繫結至類

可以使用選項模式將配置繫結到表示相關設定組的類。 有關更多資訊,請參見ASP.NET Core 中的選項模式

配置值作為字串返回,但呼叫 Bind可以構造 POCO 物件。 BindMicrosoft.Extensions.Configuration.Binder 包中,後者在 Microsoft.AspNetCore.App 元包中。

示例應用包含 Starship 模型 (Models/Starship.cs):

public class Starship
{
    public string Name { get; set; }
    public string Registry { get; set; }
    public string Class { get; set; }
    public decimal Length { get; set; }
    public bool Commissioned { get; set; }
}

當示例應用使用 JSON 配置提供程式載入配置時,starship.json 檔案的 starship 節會建立配置:

{
  "starship": {
    "name": "USS Enterprise",
    "registry": "NCC-1701",
    "class": "Constitution",
    "length": 304.8,
    "commissioned": false
  },
  "trademark": "Paramount Pictures Corp. http://www.paramount.com"
}

建立以下配置鍵值對:

starship:name USS Enterprise
starship:registry NCC-1701
starship:class Constitution
starship:length 304.8
starship:commissioned False
trademark Paramount Pictures Corp. http://www.paramount.com

示例應用使用 starship 鍵呼叫 GetSectionstarship 鍵值對是獨立的。 在子節傳入 Starship 類的例項時呼叫 Bind 方法。 繫結例項值後,將例項分配給用於呈現的屬性:

var starship = new Starship();
_config.GetSection("starship").Bind(starship);
Starship = starship;

GetSectionMicrosoft.Extensions.Configuration 包中,後者在Microsoft.AspNetCore.App 元包中。

繫結至物件圖

Bind能夠繫結整個 POCO 物件圖。 BindMicrosoft.Extensions.Configuration.Binder 包中,後者在Microsoft.AspNetCore.App 元包中。

該示例包含 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>();

GetMicrosoft.Extensions.Configuration.Binder 包中,後者在Microsoft.AspNetCore.App 元包中。 ASP.NET Core 1.1 或更高版本中提供了 Get<T>GetSectionMicrosoft.Extensions.Configuration 包中,後者在Microsoft.AspNetCore.App 元包中。

將陣列繫結至類

示例應用演示了本部分中介紹的概念。

Bind支援使用配置鍵中的陣列索引將陣列繫結到物件。 公開數字鍵段(:0::1:、… :{n}:)的任何陣列格式都能夠與 POCO 類陣列進行陣列繫結。 BindMicrosoft.Extensions.Configuration.Binder 包中,後者在 Microsoft.AspNetCore.App 元包中。

備註
繫結是按約定提供的。 不需要自定義配置提供程式實現陣列繫結。

記憶體中陣列處理

請考慮下表中所示的配置鍵和值。

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

使用記憶體配置提供程式在示例應用中載入這些鍵和值:

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.SetBasePath(Directory.GetCurrentDirectory());
                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);

GetSectionMicrosoft.Extensions.Configuration 包中,後者在Microsoft.AspNetCore.App 元包中。

還可以使用 ConfigurationBinder.Get<T> 語法,從而產生更精簡的程式碼:

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

繫結物件(ArrayExample 的例項)從配置接收陣列資料。

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

繫結物件中的索引 #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:3 value3

如果在 JSON 配置提供程式包含索引 #3 的條目之後繫結 ArrayExample 類例項,則 ArrayExample.Entries 陣列包含該值。

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

JSON 陣列處理

如果 JSON 檔案包含陣列,則會為具有從零開始的節索引的陣列元素建立配置鍵。 在以下配置檔案中,subsection 是一個陣列:

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

JSON 配置提供程式將配置資料讀入以下鍵值對:

json_array:key valueA
json_array:subsection:0 valueB
json_array:subsection:1 valueC
json_array:subsection:2 valueD

在示例應用中,以下 POCO 類可用於繫結配置鍵值對:

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

繫結後,JsonArrayExample.Key 儲存值 valueA。 子節值儲存在 POCO 陣列屬性 Subsection 中。

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

自定義配置提供程式

該示例應用演示瞭如何使用實體框架 (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; }
}

建立用於實現 xref:Microsoft.Extensions.Configuration.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>
            {
                { "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 class EFConfigurationSource : IConfigurationSource
{
    private readonly Action<DbContextOptionsBuilder> _optionsAction;

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

    public IConfigurationProvider Build(IConfigurationBuilder builder)
    {
        return new EFConfigurationProvider(_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.SetBasePath(Directory.GetCurrentDirectory());
                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>();
}

在啟動期間訪問配置

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 檢視中訪問配置

若要訪問 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>

從外部程式集新增配置

通過 IHostingStartup 實現,可在啟動時從應用 Startup 類之外的外部程式集嚮應用新增增強功能。 有關更多資訊,請參見在 ASP.NET Core 中使用承載啟動程式集

相關文章