ASP.NET Core 的設定

作者:Rick AndersonKirk Larkin

注意

這不是這篇文章的最新版本。 如需目前版本,請參閱本文的 .NET 8 版本

重要

這些發行前產品的相關資訊在產品正式發行前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。

如需目前版本,請參閱本文的 .NET 8 版本

ASP.NET Core 中的應用程式設定是使用一或多個設定提供者來執行的。 設定提供者會使用各種設定來源從機碼值組中讀取設定資料:

  • 設定檔案,例如 appsettings.json
  • 環境變數
  • Azure Key Vault
  • Azure 應用程式組態
  • 命令列引數
  • 自訂提供者 (已安裝或已建立)
  • 目錄檔案
  • 記憶體內部 .NET 物件

此文章提供 ASP.NET Core 中的設定相關資訊。 如需在主控台應用程式中使用設定的相關資訊,請參閱 .NET 設定

應用程式與主機設定

ASP.NET Core 應用程式會設定並啟動「主機」。 主機負責應用程式啟動和存留期管理。 ASP.NET Core 範本會建立包含主機的 WebApplicationBuilder。 雖然某些設定可在主機與應用程式設定提供者中完成,但一般只有主機所需的設定應該在主機設定中完成。

應用程式設定具有最高優先順序,我們將在下一節中詳述。 主機設定遵循應用程式設定,而且已在此文章中描述。

預設應用程式設定來源

使用 dotnet new 或 Visual Studio 建立的 ASP.NET Core Web 應用程式會產生下列程式碼:

var builder = WebApplication.CreateBuilder(args);

WebApplication.CreateBuilder 會初始化具有預先設定之預設值的之 WebApplicationBuilder 類別的新執行個體。 已初始化的 WebApplicationBuilder (builder) 會以下列順序為應用程式提供下列設定 (從最高到最低優先順序):

  1. 使用命令列設定提供者的命令列引數。
  2. 使用未附加前置詞之環境變數設定提供者的未附加前置詞之環境變數。
  3. 應用程式在 Development 環境中執行時的使用者密碼
  4. 使用 JSON 設定提供者appsettings.{Environment}.json。 例如,appsettings.Production.jsonappsettings.Development.json
  5. 使用 JSON 設定提供者appsettings.json
  6. 使用下一節所述的主機設定來遞補。

預設主機設定來源

下列清單包含 WebApplicationBuilder 的預設主機設定來源 (從最高到最低優先順序):

  1. 使用命令列設定提供者的命令列引數
  2. 使用環境變數設定提供者且具有 DOTNET_ 前置詞的環境變數。
  3. 使用環境變數設定提供者且具有 ASPNETCORE_ 前置詞的環境變數。

對於 .NET 一般主機Web 主機,預設主機設定來源 (從最高到最低優先順序) 為:

  1. 使用環境變數設定提供者且具有 ASPNETCORE_ 前置詞的環境變數。
  2. 使用命令列設定提供者的命令列引數
  3. 使用環境變數設定提供者且具有 DOTNET_ 前置詞的環境變數。

當在主機與應用程式中設定設定值時,會使用應用程式設定。

主機變數

下列變數已在主機建立器初始化期間的早期鎖定,而且不會受應用程式設定影響:

每個其他主機設定都是從應用程式設定而非主機設定中讀取。

URLS 是不屬於啟動程序設定的許多常見主機設定之一。 就像不存在於先前清單中的每個其他主機設定一樣,稍後會從應用程式設定讀取 URLS。主機設定是應用程式設定的後援,因此主機設定可用來設定 URLS,但其將由應用程式設定中的任何設定來源 (如 appsettings.json) 覆寫。

如需詳細資訊,請參閱變更內容根目錄、應用程式名稱和環境 (部分機器翻譯) 與依環境變數或命令列變更內容根目錄、應用程式名稱和環境 (部分機器翻譯)

此文章中的剩餘小節指的是應用程式設定。

應用程式設定提供者

下列程式碼會依照設定提供者的新增順序顯示已啟用的設定提供者:

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() + "\n";
        }

        return Content(str);
    }
}

前面的最高到最低優先順序預設設定來源清單以提供者新增至範本產生之應用程式的相反順序顯示提供者。 例如,JSON 設定提供者是在命令列設定提供者之前新增。

後面新增的設定提供者具有較高的優先順序,而且會覆寫先前的機碼設定。 例如,若同時在 appsettings.json 與環境中設定 MyKey,將會使用環境值。 使用預設設定提供者,命令列設定提供者會覆寫所有其他提供者。

如需有關 CreateBuilder 的詳細資訊,請參閱預設建立器設定 (部分機器翻譯)。

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": "*"
}

來自範例下載的下列程式碼會顯示數個上述組態設定:

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

預設的 JsonConfigurationProvider 會以下列順序載入設定:

  1. appsettings.json
  2. appsettings.{Environment}.json:例如,appsettings.Production.jsonappsettings.Development.json 檔案。 檔案的環境版本是以 IHostingEnvironment.EnvironmentName 為基礎來載入的。 如需詳細資訊,請參閱在 ASP.NET Core 中使用多個環境 (部分機器翻譯)。

appsettings.{Environment}.json 值會覆寫 appsettings.json 中的機碼。 例如,根據預設:

  • 在開發環境中,appsettings.Development.json 設定會覆寫在 appsettings.json 中找到的值。
  • 在生產環境中,appsettings.Production.json 設定會覆寫在 appsettings.json 中找到的值。 例如,將應用程式部署到 Azure 時。

若必須保證設定值,請參閱 GetValue (部分機器翻譯)。 上述範例只會讀取字串,而且不支援預設值。

使用預設設定,appsettings.jsonappsettings.{Environment}.json 檔案會使用 reloadOnChange: true 來啟用。 在應用程式啟動之後appsettings.jsonappsettings.{Environment}.json 檔案所做的變更會由 JSON 設定提供者讀取。

appsettings.json 中的註解

appsettings.jsonappsettings.{Environment}.json 檔案中的註解支援使用 JavaScript 或 C# 樣式註解

使用選項模式繫結階層式設定資料

讀取相關設定值的慣用方式是使用選項模式 (部分機器翻譯)。 例如,為讀取下列設定值:

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

建立下列 PositionOptions 類別:

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

    public string Title { get; set; } = String.Empty;
    public string Name { get; set; } = String.Empty;
}

選項類別:

  • 必須為非抽象,且具有公用的無參數建構函式。
  • 型別的所有公用讀取/寫入屬性都會繫結。
  • 欄位繫結。 在上述程式碼中,Position 未繫結: 會使用 Position 欄位,因此當您將類別繫結到設定提供者時,不需要以硬式編碼方式將字串 "Position" 放在應用程式中。

下列程式碼範例:

  • 呼叫 ConfigurationBinder.Bind 以將 PositionOptions 類別繫結到 Position 區段。
  • 顯示 Position 設定資料。
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} \n" +
                       $"Name: {positionOptions.Name}");
    }
}

在上述程式碼中,根據預設值,會讀取在應用程式啟動之後對 JSON 設定檔所做的變更。

ConfigurationBinder.Get<T> 會繫結並傳回指定的型別。 ConfigurationBinder.Get<T> 可能比使用 ConfigurationBinder.Bind 還方便。 下列程式碼會示範如何搭配 PositionOptions 類別使用 ConfigurationBinder.Get<T>

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} \n" +
                       $"Name: {positionOptions.Name}");
    }
}

在上述程式碼中,根據預設值,會讀取在應用程式啟動之後對 JSON 設定檔所做的變更。

使用選項模式的替代方式是繫結 Position 區段並將其新增至相依性插入服務容器。 在下列程式碼中,PositionOptions 會使用 Configure 新增到服務容器,並繫結到設定:

using ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<PositionOptions>(
    builder.Configuration.GetSection(PositionOptions.Position));

var app = builder.Build();

使用上述程式碼,下列程式碼會讀取位置選項:

public class Test2Model : PageModel
{
    private readonly PositionOptions _options;

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

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

在上述程式碼中,不會讀取在應用程式啟動之後對 JSON 設定檔所做的變更。 若要讀取在應用程式啟動之後所做的變更,請使用 IOptionsSnapshot

使用預設設定,appsettings.jsonappsettings.{Environment}.json 檔案會使用 reloadOnChange: true 來啟用。 在應用程式啟動之後appsettings.jsonappsettings.{Environment}.json 檔案所做的變更會由 JSON 設定提供者讀取。

如需有關新增其他 JSON 設定檔的資訊,請參閱此文件中的 JSON 設定提供者

結合服務集合

請考量會註冊服務並設定選項的下列內容:

using ConfigSample.Options;
using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<PositionOptions>(
    builder.Configuration.GetSection(PositionOptions.Position));
builder.Services.Configure<ColorOptions>(
    builder.Configuration.GetSection(ColorOptions.Color));

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

var app = builder.Build();

相關註冊群組可移至擴充方法,以註冊服務。 例如,設定服務會新增至下列類別:

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

        public static IServiceCollection AddMyDependencyGroup(
             this IServiceCollection services)
        {
            services.AddScoped<IMyDependency, MyDependency>();
            services.AddScoped<IMyDependency2, MyDependency2>();

            return services;
        }
    }
}

剩餘的服務會類似的類別中註冊。 下列程式碼使用新增擴充方法來註冊服務:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services
    .AddConfig(builder.Configuration)
    .AddMyDependencyGroup();

builder.Services.AddRazorPages();

var app = builder.Build();

注意:每個 services.Add{GROUP_NAME} 擴充方法都會新增並可能會設定服務。 例如,AddControllersWithViews 會新增具有所要求檢視的服務 MVC 控制器,而 AddRazorPages 會新增 Razor Pages 所要求的服務。

安全性與使用者祕密

設定資料方針:

  • 永遠不要將密碼或其他敏感性資料儲存在設定提供者程式碼或純文字設定檔中。 祕密管理員工具可以用來儲存開發環境中的密碼。
  • 不要在開發或測試環境中使用生產環境祕密。
  • 請在專案外部指定祕密,以防止其意外認可至開放原始碼存放庫。

根據預設,使用者祕密設定來源會在 JSON 設定來源之後註冊。 因此,使用者祕密金鑰的優先順序高於 appsettings.jsonappsettings.{Environment}.json 中金鑰的優先順序。

如需有關儲存密碼或其他敏感性資料的詳細資訊:

Azure Key Vault 可安全地儲存 ASP.NET Core 應用程式的應用程式祕密。 如需詳細資訊,請參閱 ASP.NET Core 中的 Azure Key Vault 設定提供者 (部分機器翻譯)。

未附加前置詞的環境變數

未附加前置詞之環境變數指的是那些已附加 ASPNETCORE_DOTNET_ 前置詞之環境變數以外的環境變數。 例如,ASP.NET Core Web 應用程式範本會在 launchSettings.json 中設定 "ASPNETCORE_ENVIRONMENT": "Development"。 如需有關 ASPNETCORE_DOTNET_ 環境變數的詳細資訊,請參閱:

使用預設設定,EnvironmentVariablesConfigurationProvider 會在讀取 appsettings.jsonappsettings.{Environment}.json使用者祕密後,從環境變數機碼值組載入設定。 因此,從環境讀取的機碼值會覆寫從 appsettings.jsonappsettings.{Environment}.json 與使用者祕密讀取的值。

: 分隔符號不適用於所有平台上的環境變數階層式機碼。 __,雙底線,為:

  • 所有平台都支援。 例如,Bash 不支援 : 分隔符號,但支援 __
  • 自動由 : 取代

下列 set 命令:

  • 在 Windows 上設定上述範例的環境機碼與值。
  • 使用範例下載時測試設定。 dotnet run 命令必須在專案目錄中執行。
set MyKey="My key from Environment"
set Position__Title=Environment_Editor
set Position__Name=Environment_Rick
dotnet run

上述環境設定:

  • 只會在從其所設定命令視窗啟動的處理序中進行設定。
  • 將不會由使用 Visual Studio 啟動的瀏覽器讀取。

下列 setx 命令也可用來在 Windows 上設定環境機碼與值。 不同於 setsetx 設定會予以保存。 /M 會在系統環境中設定該變數。 如果未使用 /M 切換開關,則會設定使用者環境變數。

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

測試上述命令是否會覆寫 appsettings.jsonappsettings.{Environment}.json

  • 使用 Visual Studio:結束並重新啟動 Visual Studio。
  • 使用 CLI:啟動新的命令視窗,然後輸入 dotnet run

使用字串呼叫 AddEnvironmentVariables,以指定環境變數的前置詞:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Configuration.AddEnvironmentVariables(prefix: "MyCustomPrefix_");

var app = builder.Build();

在上述程式碼中:

  • builder.Configuration.AddEnvironmentVariables(prefix: "MyCustomPrefix_") 會在預設設定提供者之後新增。 如需有關排定設定提供者優先順序的範例,請參閱 JSON 設定提供者
  • 使用 MyCustomPrefix_ 前置詞設定的環境變數會覆寫預設設定提供者。 這包括沒有前置詞的環境變數。

讀取設定機碼值組時,會移除前置詞。

下列命令會測試自訂前置詞:

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

預設設定會載入具有 DOTNET_ASPNETCORE_ 前置詞的環境變數與命令列引數。 ASP.NET Core 會為主機與應用程式設定使用 DOTNET_ASPNETCORE_ 前置詞,但不會為使用者設定使用。 如需主機與應用程式設定的詳細資訊,請參閱 .NET 泛型主機 (部分機器翻譯)。

Azure App Service 上,選取 [設定] > [組態] 頁面上的 [新增應用程式設定]。 Azure App Service 應用程式設定為:

  • 在待用及透過加密通道傳輸時加密。
  • 公開為環境變數。

如需詳細資訊,請參閱 Azure App:使用 Azure 入口網站覆寫應用程式設定

如需 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"
        }
    ]
}

環境變數

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 範本會產生 launchSettings.json 檔案,此檔案會將端點設定設定為:

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

設定 applicationUrl 會設定 ASPNETCORE_URLS 環境變數並覆寫環境中設定的值。

在 Linux 上逸出環境變數

在 Linux 上,必須逸出 URL 環境變數的值,systemd 才能加以剖析。 使用 Linux 工具 systemd-escape,這會得到 http:--localhost:5001

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

顯示環境變數

下列程式碼會在應用程式啟動時顯示環境變數與值,這在針對環境設定進行偵錯時很有幫助:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

foreach (var c in builder.Configuration.AsEnumerable())
{
    Console.WriteLine(c.Key + " = " + c.Value);
}

命令列

使用預設設定,CommandLineConfigurationProvider 會在下列設定來源之後,從命令列引數機碼值組載入設定:

  • appsettings.jsonappsettings.{Environment}.json 檔案。
  • 開發環境中的應用程式祕密
  • 環境變數。

根據預設,在命令列上設定的設定值會覆寫使用所有其他設定提供者設定的設定值。

命令列引數

下列命令會使用 = 設定機碼與值:

dotnet run MyKey="Using =" 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

機碼值:

  • 必須跟在 = 後面,或當值後面接著空格時,機碼必須有 --/ 前置詞。
  • 如果使用 =,則不是必要項。 例如: MySetting=

在相同的命令中,請不要混用使用 = 的命令列引數機碼值組與使用空格的機碼值組。

切換對應

參數對應允許機碼名稱取代邏輯。 將切換取代的字典提供給 AddCommandLine 方法。

使用切換對應字典時,會檢查字典中是否有任何索引鍵符合命令列引數所提供的索引鍵。 如果在字典中找到命令列機碼,則會傳回字典值以在應用程式的設定中設定機碼值組。 所有前面加上單虛線 (-) 的命令列索引鍵都需要切換對應。

切換對應字典索引鍵規則:

  • 切換的開頭必須是 ---
  • 切換對應字典不能包含重複索引鍵。

若要使用切換對應字典,請將其傳遞到對 AddCommandLine 的呼叫中:


var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

builder.Configuration.AddCommandLine(args, switchMappings);

var app = builder.Build();

執行下列命令工作以測試機碼取代:

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

下列程式碼顯示已取代屬性的機碼值:

public class Test3Model : PageModel
{
    private readonly IConfiguration Config;

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

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

針對使用切換對應的應用程式,呼叫 CreateDefaultBuilder 不應傳遞引數。 CreateDefaultBuilder 方法的 AddCommandLine 呼叫不包括對應的切換,且沒有任何方式可以將切換對應字典傳遞給 CreateDefaultBuilder。 解決方式並非將引數傳遞給 CreateDefaultBuilder,而是允許 ConfigurationBuilder 方法的 AddCommandLine 方法同時處理引數與切換對應字典。

使用 Visual Studio 設定環境與命令列引數

您可以在 Visual Studio 中從啟動設定檔對話方塊設定環境與命令列引數:

  • 在 [方案總管] 中,以滑鼠右鍵按一下專案,然後選取 [屬性]
  • 選取 [偵錯] > [一般] 索引標籤,然後選取 [開啟偵錯啟動設定檔 UI]

階層式設定資料

設定 API 可透過在設定機碼中使用分隔符號來壓平合併階層式資料,以讀取階層式設定資料。

範例下載包含下列 appsettings.json 檔案:

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

來自範例下載的下列程式碼會顯示數個組態設定:

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

讀取階層式設定資料的慣用方式是使用選項模式。 如需詳細資訊,請參閱此文件中的繫結階層式設定資料

GetSectionGetChildren 方法可用來在設定資料中隔離區段與區段的子系。 GetSection,、 GetChildren 與 Exists 中說明這些方法。

設定機碼與值

設定機碼:

  • 不區分大小寫。 例如,ConnectionStringconnectionstring 會視為對等機碼。
  • 若已在多個設定提供者中設定機碼與值,則會使用來自最後一個新增之提供者的值。 如需詳細資訊,請參閱預設設定
  • 階層式機碼
    • 在設定 API 內,冒號分隔字元 (:) 可在所有平台上運作。
    • 在環境變數中,冒號分隔字元可能無法在所有平台上運作。 所有平台都支援雙底線 (__),且雙底線會自動轉換為冒號 :
    • 在 Azure Key Vault 中,階層式機碼使用 -- 作為分隔符號。 在祕密載入到應用程式的設定時,Azure Key Vault 設定提供者會自動將 -- 取代為 :
  • ConfigurationBinder 支援在設定機碼中使用陣列索引將陣列繫結到物件。 將陣列繫結到類別一節說明陣列繫結。

設定值:

  • 為字串。
  • Null 值無法存放在設定中或繫結到物件。

設定提供者

下表顯示可供 ASP.NET Core 應用程式使用的設定提供者。

Provider 從提供設定
Azure Key Vault 組態提供者 Azure Key Vault
Azure 應用程式設定提供者 Azure 應用程式組態
命令列設定提供者 命令列參數
自訂設定提供者 自訂來源
環境變數設定提供者 環境變數
檔案設定提供者 INI、JSON 與 XML 檔案
每個檔案機碼設定提供者 目錄檔案
記憶體設定提供者 記憶體內集合
使用者祕密 使用者設定檔目錄中的檔案

系統會依照設定來源的設定提供者的指定順序讀入設定來源。 在您的程式碼中針對應用程式所需之底層設定來源的優先順序,為設定提供者排序。

典型的設定提供者順序是:

  1. appsettings.json
  2. appsettings.{Environment}.json
  3. 使用者祕密
  4. 使用環境變數設定提供者的環境變數。
  5. 使用命令列設定提供者的命令列引數。

將命令列設定提供者新增到提供者序列結尾,以讓命令列引數覆寫由其他提供者所設定的設定是常見做法。

上述提供者序列用於預設設定

連接字串前置詞

設定 API 具有四個連接字串環境變數的特殊處理規則。 這些連接字串涉及為應用程式環境設定 Azure 連接字串。 資料表中所顯示具有前置詞的環境變數會使用預設設定載入應用程式,或是當未提供任何前置詞給 AddEnvironmentVariables 時。

連接字串前置詞 Provider
CUSTOMCONNSTR_ 自訂提供者
MYSQLCONNSTR_ MySQL
SQLAZURECONNSTR_ Azure SQL Database
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 是用於從檔案系統載入設定的基底類別。 下列設定提供者衍生自 FileConfigurationProvider

INI 設定提供者

IniConfigurationProvider 會在執行階段從 INI 檔案機碼值組載入設定。

下列程式碼會新增數個設定提供者:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddIniFile("MyIniConfig.ini", optional: true, reloadOnChange: true)
    .AddIniFile($"MyIniConfig.{builder.Environment.EnvironmentName}.ini",
                optional: true, reloadOnChange: true);

builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

在上述程式碼中,MyIniConfig.iniMyIniConfig.{Environment}.ini 檔案中的設定已由下列項目中的設定覆寫:

範例下載包含下列 MyIniConfig.ini 檔案:

MyKey="MyIniConfig.ini Value"

[Position]
Title="My INI Config title"
Name="My INI Config name"

[Logging:LogLevel]
Default=Information
Microsoft=Warning

來自範例下載的下列程式碼會顯示數個上述組態設定:

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

JSON 設定提供者

JsonConfigurationProvider 會從 JSON 檔案機碼值組載入設定。

多載可以指定:

  • 檔案是否為選擇性。
  • 檔案變更時是否要重新載入設定。

請考慮下列程式碼:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddJsonFile("MyConfig.json",
        optional: true,
        reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

上述 程式碼:

  • 使用下列選項設定 JSON 設定提供者以載入 MyConfig.json 檔案:
    • optional: true:檔案為選擇性。
    • reloadOnChange: true:儲存變更時會重新載入該檔案。
  • MyConfig.json 檔案之前讀取預設設定提供者MyConfig.json 檔案中的設定會覆寫預設設定提供者 (包括環境變數設定提供者命令列設定提供者) 中的設定。

您通常想讓自訂 JSON 檔案覆寫環境變數設定提供者命令列設定提供者中設定的值。

XML 設定提供者

XmlConfigurationProvider 會在執行階段從 XML 檔案機碼值組載入設定。

下列程式碼會新增數個設定提供者:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddXmlFile("MyXMLFile.xml", optional: true, reloadOnChange: true)
    .AddXmlFile($"MyXMLFile.{builder.Environment.EnvironmentName}.xml",
                optional: true, reloadOnChange: true);

builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

在上述程式碼中,MyXMLFile.xmlMyXMLFile.{Environment}.xml 檔案中的設定已由下列項目中的設定覆寫:

範例下載包含下列 MyXMLFile.xml 檔案:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <MyKey>MyXMLFile Value</MyKey>
  <Position>
    <Title>Title from  MyXMLFile</Title>
    <Name>Name from MyXMLFile</Name>
  </Position>
  <Logging>
    <LogLevel>
      <Default>Information</Default>
      <Microsoft>Warning</Microsoft>
    </LogLevel>
  </Logging>
</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

每個檔案機碼設定提供者

KeyPerFileConfigurationProvider 使用目錄的檔案做為設定機碼值組。 機碼是檔案名稱。 值包含檔案的內容。 每個檔案機碼設定提供者是在 Docker 裝載案例中使用。

若要啟用每個檔案機碼設定,請在 ConfigurationBuilder 的執行個體上呼叫 AddKeyPerFile 延伸模組方法。 檔案的 directoryPath 必須是絕對路徑。

多載允許指定:

  • 設定來源的 Action<KeyPerFileConfigurationSource> 委派。
  • 目錄是否為選擇性與目錄的路徑。

雙底線 (__) 是做為檔案名稱中的設定金鑰分隔符號使用。 例如,檔案名稱 Logging__LogLevel__System 會產生設定金鑰 Logging:LogLevel:System

建置主機時呼叫 ConfigureAppConfiguration 以指定應用程式的設定:

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

記憶體設定提供者

MemoryConfigurationProvider 使用記憶體內集合做為設定機碼值組。

下列程式碼會將記憶體收集新增至設定系統:

var builder = WebApplication.CreateBuilder(args);

var Dict = new Dictionary<string, string>
        {
           {"MyKey", "Dictionary MyKey Value"},
           {"Position:Title", "Dictionary_Title"},
           {"Position:Name", "Dictionary_Name" },
           {"Logging:LogLevel:Default", "Warning"}
        };

builder.Configuration.AddInMemoryCollection(Dict);
builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

來自範例下載的下列程式碼會顯示上述組態設定:

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 設定提供者

如需另一個使用 MemoryConfigurationProvider 的範例,請參閱繫結陣列

Kestrel 端點設定

Kestrel 特定端點設定會覆寫所有跨伺服器端點設定。 跨伺服器端點設定包括:

請考慮 ASP.NET Core Web 應用程式中使用的下列 appsettings.json 檔案。

{
  "Kestrel": {
    "Endpoints": {
      "Https": {
        "Url": "https://localhost:9999"
      }
    }
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
} 

當上述反白顯示的標記用於 ASP.NET Core Web 應用程式應用程式從命令列使用下列跨伺服器端點設定啟動時:

dotnet run --urls="https://localhost:7777"

Kestrel 會繫結到特別針對 appsettings.json 檔案 (https://localhost:9999) 而非 https://localhost:7777 中的 Kestrel 設定的端點。

請考慮設定為環境變數的 Kestrel 特定端點:

set Kestrel__Endpoints__Https__Url=https://localhost:8888

在上述環境變數中,Https 是 Kestrel 特定端點的名稱。 上述 appsettings.json 檔案也定義名為 Https 的 Kestrel 特定端點。 根據預設,使用環境變數設定提供者的環境變數會在 appsettings.{Environment}.json 之後讀取,因此會針對 Https 端點使用上述環境變數。

GetValue

ConfigurationBinder.GetValue 會從具有所指定機碼的設定擷取單一值,並將其轉換為指定的型別:

public class TestNumModel : PageModel
{
    private readonly IConfiguration Configuration;

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

    public ContentResult OnGet()
    {
        var number = Configuration.GetValue<int>("NumberKey", 99);
        return Content($"{number}");
    }
}

在上述程式碼中,若在設定中找不到 NumberKey,則會使用預設值 99

GetSection、GetChildren 與 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 新增到設定提供者:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddJsonFile("MySubsection.json",
                 optional: true,
                 reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

GetSection

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 與 Exists

下列程式碼會呼叫 IConfiguration.GetChildren 並傳回 section2:subsection0 的值:

public class TestSection4Model : PageModel
{
    private readonly IConfiguration Config;

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

    public ContentResult OnGet()
    {
        string s = "";
        var selection = Config.GetSection("section2");
        if (!selection.Exists())
        {
            throw new 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 以確認區段是否存在:

繫結陣列

ConfigurationBinder.Bind 支援在設定機碼中使用陣列索引將陣列繫結到物件。 任何公開數值機碼區段的陣列格式都能以陣列方式繫結到 POCO 類別陣列。

考慮來自範例下載MyArray.json

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

下列程式碼會將 MyArray.json 新增到設定提供者:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddJsonFile("MyArray.json",
                 optional: true,
                 reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

下列程式碼會讀取設定並顯示值:

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>();
        if (_array == null)
        {
            throw new ArgumentNullException(nameof(_array));
        }
        string s = String.Empty;

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

        return Content(s);
    }
}
public class ArrayExample
{
    public string[]? Entries { get; set; } 
}

上述程式碼會傳回下列輸出:

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 項目。

自訂設定提供者

範例應用程式示範如何建立會使用 Entity Framework (EF) 從資料庫讀取設定機碼值組的基本設定提供者。

提供者具有下列特性:

  • EF 記憶體內資料庫會用於示範用途。 若要使用需要連接字串的資料庫,請實作第二個 ConfigurationBuilder 以從另一個設定提供者提供連接字串。
  • 啟動時,該提供者會將資料庫資料表讀入到設定中。 該提供者不會以個別機碼為基礎查詢資料庫。
  • 未實作變更時重新載入,因此在應用程式啟動後更新資料庫對應用程式設定沒有影響。

定義 EFConfigurationValue 實體來在資料庫中存放設定值。

Models/EFConfigurationValue.cs

public class EFConfigurationValue
{
    public string Id { get; set; } = String.Empty;
    public string Value { get; set; } = String.Empty;
}

新增 EFConfigurationContext 以存放及存取已設定的值。

EFConfigurationProvider/EFConfigurationContext.cs

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

    public DbSet<EFConfigurationValue> Values => Set<EFConfigurationValue>();
}

建立會實作 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) => new EFConfigurationProvider(_optionsAction);
}

透過繼承自 ConfigurationProvider 來建立自訂設定提供者。 若資料庫是空的,設定提供者會初始化資料庫。 因為設定機碼不區分大小寫,所以會使用不區分大小寫的比較子 (StringComparer.OrdinalIgnoreCase) 來建立用來初始化資料庫的字典。

EFConfigurationProvider/EFConfigurationProvider.cs

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

    Action<DbContextOptionsBuilder> OptionsAction { get; }

    public override void Load()
    {
        var builder = new DbContextOptionsBuilder<EFConfigurationContext>();

        OptionsAction(builder);

        using (var dbContext = new EFConfigurationContext(builder.Options))
        {
            if (dbContext == null || dbContext.Values == null)
            {
                throw new Exception("Null DB context");
            }
            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-2005
        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." }
            };

        if (dbContext == null || dbContext.Values == null)
        {
            throw new Exception("Null DB context");
        }

        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

//using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddEFConfiguration(
    opt => opt.UseInMemoryDatabase("InMemoryDb"));

var app = builder.Build();

app.Run();

使用相依性插入 (DI) 來存取設定

可以透過解析 IConfiguration 服務,使用相依性插入 (DI) 將設定插入到服務:

public class Service
{
    private readonly IConfiguration _config;

    public Service(IConfiguration config) =>
        _config = config;

    public void DoSomething()
    {
        var configSettingValue = _config["ConfigSetting"];

        // ...
    }
}

如需有關如何使用 IConfiguration 存取值的詳細資訊,請參閱此文章中的 GetValueGetSection、GetChildren 與 Exists

存取 Razor Pages 中的設定

下列程式碼會顯示 Razor Pages 中的設定資料:

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

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

在下列程式碼中,MyOptions 會使用 Configure 新增到服務容器,並繫結到設定:

using SampleApp.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<MyOptions>(
    builder.Configuration.GetSection("MyOptions"));

var app = builder.Build();

下列標記使用 @injectRazor 指示詞來解析及顯示選項值:

@page
@model SampleApp.Pages.Test3Model
@using Microsoft.Extensions.Options
@using SampleApp.Models
@inject IOptions<MyOptions> optionsAccessor


<p><b>Option1:</b> @optionsAccessor.Value.Option1</p>
<p><b>Option2:</b> @optionsAccessor.Value.Option2</p>

存取 MVC 檢視檔案中的設定

下列程式碼會顯示 MVC 檢視中的設定資料:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

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

存取 Program.cs 中的設定

下列程式碼會存取 Program.cs 檔案中的設定。

var builder = WebApplication.CreateBuilder(args);

var key1 = builder.Configuration.GetValue<string>("KeyOne");

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

var key2 = app.Configuration.GetValue<int>("KeyTwo");
var key3 = app.Configuration.GetValue<bool>("KeyThree");

app.Logger.LogInformation("KeyOne: {KeyOne}", key1);
app.Logger.LogInformation("KeyTwo: {KeyTwo}", key2);
app.Logger.LogInformation("KeyThree: {KeyThree}", key3);

app.Run();

在上述範例的 appsettings.json

{
  ...
  "KeyOne": "Key One Value",
  "KeyTwo": 1999,
  "KeyThree": true
}

使用委派設定選項

在委派中設定的選項會覆寫在設定提供者中設定的值。

在下列程式碼中,IConfigureOptions<TOptions> 服務會新增至服務容器。 其使用委派為 MyOptions 設定值:

using SampleApp.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<MyOptions>(myOptions =>
{
    myOptions.Option1 = "Value configured in delegate";
    myOptions.Option2 = 500;
});

var app = builder.Build();

下列程式碼會顯示選項值:

public class Test2Model : PageModel
{
    private readonly IOptions<MyOptions> _optionsDelegate;

    public Test2Model(IOptions<MyOptions> optionsDelegate )
    {
        _optionsDelegate = optionsDelegate;
    }

    public ContentResult OnGet()
    {
        return Content($"Option1: {_optionsDelegate.Value.Option1} \n" +
                       $"Option2: {_optionsDelegate.Value.Option2}");
    }
}

在上述範例中,Option1Option2 的值已在 appsettings.json 中指定,然後會由已設定的委派覆寫。

主機與應用程式組態的比較

設定及啟動應用程式之前,會先設定及啟動「主機」。 主機負責應用程式啟動和存留期管理。 應用程式與主機都是使用此主題中所述的設定提供者來設定的。 主機組態機碼/值組也會包含在應用程式的組態中。 如需建置主機時如何使用設定提供者,以及設定來源如何影響主機設定的詳細資訊,請參閱 ASP.NET Core 基本概念的概觀 (部分機器翻譯)。

預設主機設定

如需使用 Web 主機時預設組態的詳細資料,請參閱本主題的 ASP.NET Core 2.2 版本

  • 主機組態的提供來源:
  • 已建立 Web 主機預設組態 (ConfigureWebHostDefaults):
    • Kestrel 會用作為網頁伺服器,並使用應用程式的設定提供者來設定。
    • 新增主機篩選中介軟體。
    • 如果 ASPNETCORE_FORWARDEDHEADERS_ENABLED 環境變數設定為 true,則會新增轉接的標頭中介軟體。
    • 啟用 IIS 整合。

其他設定

此主題僅適用於應用程式設定。 執行及裝載 ASP.NET Core 應用程式的其他方面是使用此主題中未涵蓋的設定檔所設定:

launchSettings.json 中設定的環境變數會覆寫系統環境中設定的環境變數。

如需從舊版 ASP.NET 移轉應用程式設定的詳細資訊,請參閱從 ASP.NET 更新至 ASP.NET Core

從外部組件新增設定

IHostingStartup 實作允許在啟動時從應用程式 Startup 類別外部的外部組件,針對應用程式新增增強功能。 如需詳細資訊,請參閱在 ASP.NET Core 中使用裝載啟動組件 (部分機器翻譯)。

組態繫結來源產生器

設定繫結來源產生器提供 AOT 和易於修剪的設定。 如需詳細資訊,請參閱設定繫結來源產生器

其他資源

ASP.NET Core 中的應用程式設定是使用一或多個設定提供者來執行的。 設定提供者會使用各種設定來源從機碼值組中讀取設定資料:

  • 設定檔案,例如 appsettings.json
  • 環境變數
  • Azure Key Vault
  • Azure 應用程式組態
  • 命令列引數
  • 自訂提供者 (已安裝或已建立)
  • 目錄檔案
  • 記憶體內部 .NET 物件

此文章提供 ASP.NET Core 中的設定相關資訊。 如需在主控台應用程式中使用設定的相關資訊,請參閱 .NET 設定

應用程式與主機設定

ASP.NET Core 應用程式會設定並啟動「主機」。 主機負責應用程式啟動和存留期管理。 ASP.NET Core 範本會建立包含主機的 WebApplicationBuilder。 雖然某些設定可在主機與應用程式設定提供者中完成,但一般只有主機所需的設定應該在主機設定中完成。

應用程式設定具有最高優先順序,我們將在下一節中詳述。 主機設定遵循應用程式設定,而且已在此文章中描述。

預設應用程式設定來源

使用 dotnet new 或 Visual Studio 建立的 ASP.NET Core Web 應用程式會產生下列程式碼:

var builder = WebApplication.CreateBuilder(args);

WebApplication.CreateBuilder 會初始化具有預先設定之預設值的之 WebApplicationBuilder 類別的新執行個體。 已初始化的 WebApplicationBuilder (builder) 會以下列順序為應用程式提供下列設定 (從最高到最低優先順序):

  1. 使用命令列設定提供者的命令列引數。
  2. 使用未附加前置詞之環境變數設定提供者的未附加前置詞之環境變數。
  3. 應用程式在 Development 環境中執行時的使用者密碼
  4. 使用 JSON 設定提供者appsettings.{Environment}.json。 例如,appsettings.Production.jsonappsettings.Development.json
  5. 使用 JSON 設定提供者appsettings.json
  6. 使用下一節所述的主機設定來遞補。

預設主機設定來源

下列清單包含 WebApplicationBuilder 的預設主機設定來源 (從最高到最低優先順序):

  1. 使用命令列設定提供者的命令列引數
  2. 使用環境變數設定提供者且具有 DOTNET_ 前置詞的環境變數。
  3. 使用環境變數設定提供者且具有 ASPNETCORE_ 前置詞的環境變數。

對於 .NET 一般主機Web 主機,預設主機設定來源 (從最高到最低優先順序) 為:

  1. 使用環境變數設定提供者且具有 ASPNETCORE_ 前置詞的環境變數。
  2. 使用命令列設定提供者的命令列引數
  3. 使用環境變數設定提供者且具有 DOTNET_ 前置詞的環境變數。

當在主機與應用程式中設定設定值時,會使用應用程式設定。

主機變數

下列變數已在主機建立器初始化期間的早期鎖定,而且不會受應用程式設定影響:

每個其他主機設定都是從應用程式設定而非主機設定中讀取。

URLS 是不屬於啟動程序設定的許多常見主機設定之一。 就像不存在於先前清單中的每個其他主機設定一樣,稍後會從應用程式設定讀取 URLS。主機設定是應用程式設定的後援,因此主機設定可用來設定 URLS,但其將由應用程式設定中的任何設定來源 (如 appsettings.json) 覆寫。

如需詳細資訊,請參閱變更內容根目錄、應用程式名稱和環境 (部分機器翻譯) 與依環境變數或命令列變更內容根目錄、應用程式名稱和環境 (部分機器翻譯)

此文章中的剩餘小節指的是應用程式設定。

應用程式設定提供者

下列程式碼會依照設定提供者的新增順序顯示已啟用的設定提供者:

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() + "\n";
        }

        return Content(str);
    }
}

前面的最高到最低優先順序預設設定來源清單以提供者新增至範本產生之應用程式的相反順序顯示提供者。 例如,JSON 設定提供者是在命令列設定提供者之前新增。

後面新增的設定提供者具有較高的優先順序,而且會覆寫先前的機碼設定。 例如,若同時在 appsettings.json 與環境中設定 MyKey,將會使用環境值。 使用預設設定提供者,命令列設定提供者會覆寫所有其他提供者。

如需有關 CreateBuilder 的詳細資訊,請參閱預設建立器設定 (部分機器翻譯)。

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": "*"
}

來自範例下載的下列程式碼會顯示數個上述組態設定:

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

預設的 JsonConfigurationProvider 會以下列順序載入設定:

  1. appsettings.json
  2. appsettings.{Environment}.json:例如,appsettings.Production.jsonappsettings.Development.json 檔案。 檔案的環境版本是以 IHostingEnvironment.EnvironmentName 為基礎來載入的。 如需詳細資訊,請參閱在 ASP.NET Core 中使用多個環境 (部分機器翻譯)。

appsettings.{Environment}.json 值會覆寫 appsettings.json 中的機碼。 例如,根據預設:

  • 在開發環境中,appsettings.Development.json 設定會覆寫在 appsettings.json 中找到的值。
  • 在生產環境中,appsettings.Production.json 設定會覆寫在 appsettings.json 中找到的值。 例如,將應用程式部署到 Azure 時。

若必須保證設定值,請參閱 GetValue (部分機器翻譯)。 上述範例只會讀取字串,而且不支援預設值。

使用預設設定,appsettings.jsonappsettings.{Environment}.json 檔案會使用 reloadOnChange: true 來啟用。 在應用程式啟動之後appsettings.jsonappsettings.{Environment}.json 檔案所做的變更會由 JSON 設定提供者讀取。

appsettings.json 中的註解

使用 JavaScript 或 C# 樣式註解支援 appsettings.jsonappsettings.{Environment}.json 檔案中的註解。

使用選項模式繫結階層式設定資料

讀取相關設定值的慣用方式是使用選項模式 (部分機器翻譯)。 例如,為讀取下列設定值:

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

建立下列 PositionOptions 類別:

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

    public string Title { get; set; } = String.Empty;
    public string Name { get; set; } = String.Empty;
}

選項類別:

  • 必須為非抽象,且具有公用的無參數建構函式。
  • 型別的所有公用讀取/寫入屬性都會繫結。
  • 欄位繫結。 在上述程式碼中,Position 未繫結: 會使用 Position 欄位,因此當您將類別繫結到設定提供者時,不需要以硬式編碼方式將字串 "Position" 放在應用程式中。

下列程式碼範例:

  • 呼叫 ConfigurationBinder.Bind 以將 PositionOptions 類別繫結到 Position 區段。
  • 顯示 Position 設定資料。
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} \n" +
                       $"Name: {positionOptions.Name}");
    }
}

在上述程式碼中,根據預設值,會讀取在應用程式啟動之後對 JSON 設定檔所做的變更。

ConfigurationBinder.Get<T> 會繫結並傳回指定的型別。 ConfigurationBinder.Get<T> 可能比使用 ConfigurationBinder.Bind 還方便。 下列程式碼會示範如何搭配 PositionOptions 類別使用 ConfigurationBinder.Get<T>

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} \n" +
                       $"Name: {positionOptions.Name}");
    }
}

在上述程式碼中,根據預設值,會讀取在應用程式啟動之後對 JSON 設定檔所做的變更。

使用選項模式的替代方式是繫結 Position 區段並將其新增至相依性插入服務容器。 在下列程式碼中,PositionOptions 會使用 Configure 新增到服務容器,並繫結到設定:

using ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<PositionOptions>(
    builder.Configuration.GetSection(PositionOptions.Position));

var app = builder.Build();

使用上述程式碼,下列程式碼會讀取位置選項:

public class Test2Model : PageModel
{
    private readonly PositionOptions _options;

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

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

在上述程式碼中,不會讀取在應用程式啟動之後對 JSON 設定檔所做的變更。 若要讀取在應用程式啟動之後所做的變更,請使用 IOptionsSnapshot

使用預設設定,appsettings.jsonappsettings.{Environment}.json 檔案會使用 reloadOnChange: true 來啟用。 在應用程式啟動之後appsettings.jsonappsettings.{Environment}.json 檔案所做的變更會由 JSON 設定提供者讀取。

如需有關新增其他 JSON 設定檔的資訊,請參閱此文件中的 JSON 設定提供者

結合服務集合

請考量會註冊服務並設定選項的下列內容:

using ConfigSample.Options;
using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<PositionOptions>(
    builder.Configuration.GetSection(PositionOptions.Position));
builder.Services.Configure<ColorOptions>(
    builder.Configuration.GetSection(ColorOptions.Color));

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

var app = builder.Build();

相關註冊群組可移至擴充方法,以註冊服務。 例如,設定服務會新增至下列類別:

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

        public static IServiceCollection AddMyDependencyGroup(
             this IServiceCollection services)
        {
            services.AddScoped<IMyDependency, MyDependency>();
            services.AddScoped<IMyDependency2, MyDependency2>();

            return services;
        }
    }
}

剩餘的服務會類似的類別中註冊。 下列程式碼使用新增擴充方法來註冊服務:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services
    .AddConfig(builder.Configuration)
    .AddMyDependencyGroup();

builder.Services.AddRazorPages();

var app = builder.Build();

注意:每個 services.Add{GROUP_NAME} 擴充方法都會新增並可能會設定服務。 例如,AddControllersWithViews 會新增具有所要求檢視的服務 MVC 控制器,而 AddRazorPages 會新增 Razor Pages 所要求的服務。

安全性與使用者祕密

設定資料方針:

  • 永遠不要將密碼或其他敏感性資料儲存在設定提供者程式碼或純文字設定檔中。 祕密管理員工具可以用來儲存開發環境中的密碼。
  • 不要在開發或測試環境中使用生產環境祕密。
  • 請在專案外部指定祕密,以防止其意外認可至開放原始碼存放庫。

根據預設,使用者祕密設定來源會在 JSON 設定來源之後註冊。 因此,使用者祕密金鑰的優先順序高於 appsettings.jsonappsettings.{Environment}.json 中金鑰的優先順序。

如需有關儲存密碼或其他敏感性資料的詳細資訊:

Azure Key Vault 可安全地儲存 ASP.NET Core 應用程式的應用程式祕密。 如需詳細資訊,請參閱 ASP.NET Core 中的 Azure Key Vault 設定提供者 (部分機器翻譯)。

未附加前置詞的環境變數

未附加前置詞之環境變數指的是那些已附加 ASPNETCORE_DOTNET_ 前置詞之環境變數以外的環境變數。 例如,ASP.NET Core Web 應用程式範本會在 launchSettings.json 中設定 "ASPNETCORE_ENVIRONMENT": "Development"。 如需有關 ASPNETCORE_DOTNET_ 環境變數的詳細資訊,請參閱:

使用預設設定,EnvironmentVariablesConfigurationProvider 會在讀取 appsettings.jsonappsettings.{Environment}.json使用者祕密後,從環境變數機碼值組載入設定。 因此,從環境讀取的機碼值會覆寫從 appsettings.jsonappsettings.{Environment}.json 與使用者祕密讀取的值。

: 分隔符號不適用於所有平台上的環境變數階層式機碼。 __,雙底線,為:

  • 所有平台都支援。 例如,Bash 不支援 : 分隔符號,但支援 __
  • 自動由 : 取代

下列 set 命令:

  • 在 Windows 上設定上述範例的環境機碼與值。
  • 使用範例下載時測試設定。 dotnet run 命令必須在專案目錄中執行。
set MyKey="My key from Environment"
set Position__Title=Environment_Editor
set Position__Name=Environment_Rick
dotnet run

上述環境設定:

  • 只會在從其所設定命令視窗啟動的處理序中進行設定。
  • 將不會由使用 Visual Studio 啟動的瀏覽器讀取。

下列 setx 命令也可用來在 Windows 上設定環境機碼與值。 不同於 setsetx 設定會予以保存。 /M 會在系統環境中設定該變數。 如果未使用 /M 切換開關,則會設定使用者環境變數。

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

測試上述命令是否會覆寫 appsettings.jsonappsettings.{Environment}.json

  • 使用 Visual Studio:結束並重新啟動 Visual Studio。
  • 使用 CLI:啟動新的命令視窗,然後輸入 dotnet run

使用字串呼叫 AddEnvironmentVariables,以指定環境變數的前置詞:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Configuration.AddEnvironmentVariables(prefix: "MyCustomPrefix_");

var app = builder.Build();

在上述程式碼中:

  • builder.Configuration.AddEnvironmentVariables(prefix: "MyCustomPrefix_") 會在預設設定提供者之後新增。 如需有關排定設定提供者優先順序的範例,請參閱 JSON 設定提供者
  • 使用 MyCustomPrefix_ 前置詞設定的環境變數會覆寫預設設定提供者。 這包括沒有前置詞的環境變數。

讀取設定機碼值組時,會移除前置詞。

下列命令會測試自訂前置詞:

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

預設設定會載入具有 DOTNET_ASPNETCORE_ 前置詞的環境變數與命令列引數。 ASP.NET Core 會為主機與應用程式設定使用 DOTNET_ASPNETCORE_ 前置詞,但不會為使用者設定使用。 如需主機與應用程式設定的詳細資訊,請參閱 .NET 泛型主機 (部分機器翻譯)。

Azure App Service 上,選取 [設定] > [組態] 頁面上的 [新增應用程式設定]。 Azure App Service 應用程式設定為:

  • 在待用及透過加密通道傳輸時加密。
  • 公開為環境變數。

如需詳細資訊,請參閱 Azure App:使用 Azure 入口網站覆寫應用程式設定

如需 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"
        }
    ]
}

環境變數

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 範本會產生 launchSettings.json 檔案,此檔案會將端點設定設定為:

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

設定 applicationUrl 會設定 ASPNETCORE_URLS 環境變數並覆寫環境中設定的值。

在 Linux 上逸出環境變數

在 Linux 上,必須逸出 URL 環境變數的值,systemd 才能加以剖析。 使用 Linux 工具 systemd-escape,這會得到 http:--localhost:5001

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

顯示環境變數

下列程式碼會在應用程式啟動時顯示環境變數與值,這在針對環境設定進行偵錯時很有幫助:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

foreach (var c in builder.Configuration.AsEnumerable())
{
    Console.WriteLine(c.Key + " = " + c.Value);
}

命令列

使用預設設定,CommandLineConfigurationProvider 會在下列設定來源之後,從命令列引數機碼值組載入設定:

  • appsettings.jsonappsettings.{Environment}.json 檔案。
  • 開發環境中的應用程式祕密
  • 環境變數。

根據預設,在命令列上設定的設定值會覆寫使用所有其他設定提供者設定的設定值。

命令列引數

下列命令會使用 = 設定機碼與值:

dotnet run MyKey="Using =" 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

機碼值:

  • 必須跟在 = 後面,或當值後面接著空格時,機碼必須有 --/ 前置詞。
  • 如果使用 =,則不是必要項。 例如: MySetting=

在相同的命令中,請不要混用使用 = 的命令列引數機碼值組與使用空格的機碼值組。

切換對應

參數對應允許機碼名稱取代邏輯。 將切換取代的字典提供給 AddCommandLine 方法。

使用切換對應字典時,會檢查字典中是否有任何索引鍵符合命令列引數所提供的索引鍵。 如果在字典中找到命令列機碼,則會傳回字典值以在應用程式的設定中設定機碼值組。 所有前面加上單虛線 (-) 的命令列索引鍵都需要切換對應。

切換對應字典索引鍵規則:

  • 切換的開頭必須是 ---
  • 切換對應字典不能包含重複索引鍵。

若要使用切換對應字典,請將其傳遞到對 AddCommandLine 的呼叫中:


var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

builder.Configuration.AddCommandLine(args, switchMappings);

var app = builder.Build();

執行下列命令工作以測試機碼取代:

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

下列程式碼顯示已取代屬性的機碼值:

public class Test3Model : PageModel
{
    private readonly IConfiguration Config;

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

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

針對使用切換對應的應用程式,呼叫 CreateDefaultBuilder 不應傳遞引數。 CreateDefaultBuilder 方法的 AddCommandLine 呼叫不包括對應的切換,且沒有任何方式可以將切換對應字典傳遞給 CreateDefaultBuilder。 解決方式並非將引數傳遞給 CreateDefaultBuilder,而是允許 ConfigurationBuilder 方法的 AddCommandLine 方法同時處理引數與切換對應字典。

使用 Visual Studio 設定環境與命令列引數

您可以在 Visual Studio 中從啟動設定檔對話方塊設定環境與命令列引數:

  • 在 [方案總管] 中,以滑鼠右鍵按一下專案,然後選取 [屬性]
  • 選取 [偵錯] > [一般] 索引標籤,然後選取 [開啟偵錯啟動設定檔 UI]

階層式設定資料

設定 API 可透過在設定機碼中使用分隔符號來壓平合併階層式資料,以讀取階層式設定資料。

範例下載包含下列 appsettings.json 檔案:

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

來自範例下載的下列程式碼會顯示數個組態設定:

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

讀取階層式設定資料的慣用方式是使用選項模式。 如需詳細資訊,請參閱此文件中的繫結階層式設定資料

GetSectionGetChildren 方法可用來在設定資料中隔離區段與區段的子系。 GetSection,、 GetChildren 與 Exists 中說明這些方法。

設定機碼與值

設定機碼:

  • 不區分大小寫。 例如,ConnectionStringconnectionstring 會視為對等機碼。
  • 若已在多個設定提供者中設定機碼與值,則會使用來自最後一個新增之提供者的值。 如需詳細資訊,請參閱預設設定
  • 階層式機碼
    • 在設定 API 內,冒號分隔字元 (:) 可在所有平台上運作。
    • 在環境變數中,冒號分隔字元可能無法在所有平台上運作。 所有平台都支援雙底線 (__),且雙底線會自動轉換為冒號 :
    • 在 Azure Key Vault 中,階層式機碼使用 -- 作為分隔符號。 在祕密載入到應用程式的設定時,Azure Key Vault 設定提供者會自動將 -- 取代為 :
  • ConfigurationBinder 支援在設定機碼中使用陣列索引將陣列繫結到物件。 將陣列繫結到類別一節說明陣列繫結。

設定值:

  • 為字串。
  • Null 值無法存放在設定中或繫結到物件。

設定提供者

下表顯示可供 ASP.NET Core 應用程式使用的設定提供者。

Provider 從提供設定
Azure Key Vault 組態提供者 Azure Key Vault
Azure 應用程式設定提供者 Azure 應用程式組態
命令列設定提供者 命令列參數
自訂設定提供者 自訂來源
環境變數設定提供者 環境變數
檔案設定提供者 INI、JSON 與 XML 檔案
每個檔案機碼設定提供者 目錄檔案
記憶體設定提供者 記憶體內集合
使用者祕密 使用者設定檔目錄中的檔案

系統會依照設定來源的設定提供者的指定順序讀入設定來源。 在您的程式碼中針對應用程式所需之底層設定來源的優先順序,為設定提供者排序。

典型的設定提供者順序是:

  1. appsettings.json
  2. appsettings.{Environment}.json
  3. 使用者祕密
  4. 使用環境變數設定提供者的環境變數。
  5. 使用命令列設定提供者的命令列引數。

將命令列設定提供者新增到提供者序列結尾,以讓命令列引數覆寫由其他提供者所設定的設定是常見做法。

上述提供者序列用於預設設定

連接字串前置詞

設定 API 具有四個連接字串環境變數的特殊處理規則。 這些連接字串涉及為應用程式環境設定 Azure 連接字串。 資料表中所顯示具有前置詞的環境變數會使用預設設定載入應用程式,或是當未提供任何前置詞給 AddEnvironmentVariables 時。

連接字串前置詞 Provider
CUSTOMCONNSTR_ 自訂提供者
MYSQLCONNSTR_ MySQL
SQLAZURECONNSTR_ Azure SQL Database
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 是用於從檔案系統載入設定的基底類別。 下列設定提供者衍生自 FileConfigurationProvider

INI 設定提供者

IniConfigurationProvider 會在執行階段從 INI 檔案機碼值組載入設定。

下列程式碼會新增數個設定提供者:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddIniFile("MyIniConfig.ini", optional: true, reloadOnChange: true)
    .AddIniFile($"MyIniConfig.{builder.Environment.EnvironmentName}.ini",
                optional: true, reloadOnChange: true);

builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

在上述程式碼中,MyIniConfig.iniMyIniConfig.{Environment}.ini 檔案中的設定已由下列項目中的設定覆寫:

範例下載包含下列 MyIniConfig.ini 檔案:

MyKey="MyIniConfig.ini Value"

[Position]
Title="My INI Config title"
Name="My INI Config name"

[Logging:LogLevel]
Default=Information
Microsoft=Warning

來自範例下載的下列程式碼會顯示數個上述組態設定:

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

JSON 設定提供者

JsonConfigurationProvider 會從 JSON 檔案機碼值組載入設定。

多載可以指定:

  • 檔案是否為選擇性。
  • 檔案變更時是否要重新載入設定。

請考慮下列程式碼:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddJsonFile("MyConfig.json",
        optional: true,
        reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

上述 程式碼:

  • 使用下列選項設定 JSON 設定提供者以載入 MyConfig.json 檔案:
    • optional: true:檔案為選擇性。
    • reloadOnChange: true:儲存變更時會重新載入該檔案。
  • MyConfig.json 檔案之前讀取預設設定提供者MyConfig.json 檔案中的設定會覆寫預設設定提供者 (包括環境變數設定提供者命令列設定提供者) 中的設定。

您通常想讓自訂 JSON 檔案覆寫環境變數設定提供者命令列設定提供者中設定的值。

XML 設定提供者

XmlConfigurationProvider 會在執行階段從 XML 檔案機碼值組載入設定。

下列程式碼會新增數個設定提供者:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddXmlFile("MyXMLFile.xml", optional: true, reloadOnChange: true)
    .AddXmlFile($"MyXMLFile.{builder.Environment.EnvironmentName}.xml",
                optional: true, reloadOnChange: true);

builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

在上述程式碼中,MyXMLFile.xmlMyXMLFile.{Environment}.xml 檔案中的設定已由下列項目中的設定覆寫:

範例下載包含下列 MyXMLFile.xml 檔案:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <MyKey>MyXMLFile Value</MyKey>
  <Position>
    <Title>Title from  MyXMLFile</Title>
    <Name>Name from MyXMLFile</Name>
  </Position>
  <Logging>
    <LogLevel>
      <Default>Information</Default>
      <Microsoft>Warning</Microsoft>
    </LogLevel>
  </Logging>
</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

每個檔案機碼設定提供者

KeyPerFileConfigurationProvider 使用目錄的檔案做為設定機碼值組。 機碼是檔案名稱。 值包含檔案的內容。 每個檔案機碼設定提供者是在 Docker 裝載案例中使用。

若要啟用每個檔案機碼設定,請在 ConfigurationBuilder 的執行個體上呼叫 AddKeyPerFile 延伸模組方法。 檔案的 directoryPath 必須是絕對路徑。

多載允許指定:

  • 設定來源的 Action<KeyPerFileConfigurationSource> 委派。
  • 目錄是否為選擇性與目錄的路徑。

雙底線 (__) 是做為檔案名稱中的設定金鑰分隔符號使用。 例如,檔案名稱 Logging__LogLevel__System 會產生設定金鑰 Logging:LogLevel:System

建置主機時呼叫 ConfigureAppConfiguration 以指定應用程式的設定:

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

記憶體設定提供者

MemoryConfigurationProvider 使用記憶體內集合做為設定機碼值組。

下列程式碼會將記憶體收集新增至設定系統:

var builder = WebApplication.CreateBuilder(args);

var Dict = new Dictionary<string, string>
        {
           {"MyKey", "Dictionary MyKey Value"},
           {"Position:Title", "Dictionary_Title"},
           {"Position:Name", "Dictionary_Name" },
           {"Logging:LogLevel:Default", "Warning"}
        };

builder.Configuration.AddInMemoryCollection(Dict);
builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

來自範例下載的下列程式碼會顯示上述組態設定:

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 設定提供者

如需另一個使用 MemoryConfigurationProvider 的範例,請參閱繫結陣列

Kestrel 端點設定

Kestrel 特定端點設定會覆寫所有跨伺服器端點設定。 跨伺服器端點設定包括:

請考慮 ASP.NET Core Web 應用程式中使用的下列 appsettings.json 檔案。

{
  "Kestrel": {
    "Endpoints": {
      "Https": {
        "Url": "https://localhost:9999"
      }
    }
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
} 

當上述反白顯示的標記用於 ASP.NET Core Web 應用程式應用程式從命令列使用下列跨伺服器端點設定啟動時:

dotnet run --urls="https://localhost:7777"

Kestrel 會繫結到特別針對 appsettings.json 檔案 (https://localhost:9999) 而非 https://localhost:7777 中的 Kestrel 設定的端點。

請考慮設定為環境變數的 Kestrel 特定端點:

set Kestrel__Endpoints__Https__Url=https://localhost:8888

在上述環境變數中,Https 是 Kestrel 特定端點的名稱。 上述 appsettings.json 檔案也定義名為 Https 的 Kestrel 特定端點。 根據預設,使用環境變數設定提供者的環境變數會在 appsettings.{Environment}.json 之後讀取,因此會針對 Https 端點使用上述環境變數。

GetValue

ConfigurationBinder.GetValue 會從具有所指定機碼的設定擷取單一值,並將其轉換為指定的型別:

public class TestNumModel : PageModel
{
    private readonly IConfiguration Configuration;

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

    public ContentResult OnGet()
    {
        var number = Configuration.GetValue<int>("NumberKey", 99);
        return Content($"{number}");
    }
}

在上述程式碼中,若在設定中找不到 NumberKey,則會使用預設值 99

GetSection、GetChildren 與 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 新增到設定提供者:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddJsonFile("MySubsection.json",
                 optional: true,
                 reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

GetSection

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 與 Exists

下列程式碼會呼叫 IConfiguration.GetChildren 並傳回 section2:subsection0 的值:

public class TestSection4Model : PageModel
{
    private readonly IConfiguration Config;

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

    public ContentResult OnGet()
    {
        string s = "";
        var selection = Config.GetSection("section2");
        if (!selection.Exists())
        {
            throw new 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 以確認區段是否存在:

繫結陣列

ConfigurationBinder.Bind 支援在設定機碼中使用陣列索引將陣列繫結到物件。 任何公開數值機碼區段的陣列格式都能以陣列方式繫結到 POCO 類別陣列。

考慮來自範例下載MyArray.json

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

下列程式碼會將 MyArray.json 新增到設定提供者:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddJsonFile("MyArray.json",
                 optional: true,
                 reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

下列程式碼會讀取設定並顯示值:

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>();
        if (_array == null)
        {
            throw new ArgumentNullException(nameof(_array));
        }
        string s = String.Empty;

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

        return Content(s);
    }
}
public class ArrayExample
{
    public string[]? Entries { get; set; } 
}

上述程式碼會傳回下列輸出:

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 項目。

自訂設定提供者

範例應用程式示範如何建立會使用 Entity Framework (EF) 從資料庫讀取設定機碼值組的基本設定提供者。

提供者具有下列特性:

  • EF 記憶體內資料庫會用於示範用途。 若要使用需要連接字串的資料庫,請實作第二個 ConfigurationBuilder 以從另一個設定提供者提供連接字串。
  • 啟動時,該提供者會將資料庫資料表讀入到設定中。 該提供者不會以個別機碼為基礎查詢資料庫。
  • 未實作變更時重新載入,因此在應用程式啟動後更新資料庫對應用程式設定沒有影響。

定義 EFConfigurationValue 實體來在資料庫中存放設定值。

Models/EFConfigurationValue.cs

public class EFConfigurationValue
{
    public string Id { get; set; } = String.Empty;
    public string Value { get; set; } = String.Empty;
}

新增 EFConfigurationContext 以存放及存取已設定的值。

EFConfigurationProvider/EFConfigurationContext.cs

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

    public DbSet<EFConfigurationValue> Values => Set<EFConfigurationValue>();
}

建立會實作 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) => new EFConfigurationProvider(_optionsAction);
}

透過繼承自 ConfigurationProvider 來建立自訂設定提供者。 若資料庫是空的,設定提供者會初始化資料庫。 因為設定機碼不區分大小寫,所以會使用不區分大小寫的比較子 (StringComparer.OrdinalIgnoreCase) 來建立用來初始化資料庫的字典。

EFConfigurationProvider/EFConfigurationProvider.cs

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

    Action<DbContextOptionsBuilder> OptionsAction { get; }

    public override void Load()
    {
        var builder = new DbContextOptionsBuilder<EFConfigurationContext>();

        OptionsAction(builder);

        using (var dbContext = new EFConfigurationContext(builder.Options))
        {
            if (dbContext == null || dbContext.Values == null)
            {
                throw new Exception("Null DB context");
            }
            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-2005
        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." }
            };

        if (dbContext == null || dbContext.Values == null)
        {
            throw new Exception("Null DB context");
        }

        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

//using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddEFConfiguration(
    opt => opt.UseInMemoryDatabase("InMemoryDb"));

var app = builder.Build();

app.Run();

使用相依性插入 (DI) 來存取設定

可以透過解析 IConfiguration 服務,使用相依性插入 (DI) 將設定插入到服務:

public class Service
{
    private readonly IConfiguration _config;

    public Service(IConfiguration config) =>
        _config = config;

    public void DoSomething()
    {
        var configSettingValue = _config["ConfigSetting"];

        // ...
    }
}

如需有關如何使用 IConfiguration 存取值的詳細資訊,請參閱此文章中的 GetValueGetSection、GetChildren 與 Exists

存取 Razor Pages 中的設定

下列程式碼會顯示 Razor Pages 中的設定資料:

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

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

在下列程式碼中,MyOptions 會使用 Configure 新增到服務容器,並繫結到設定:

using SampleApp.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<MyOptions>(
    builder.Configuration.GetSection("MyOptions"));

var app = builder.Build();

下列標記使用 @injectRazor 指示詞來解析及顯示選項值:

@page
@model SampleApp.Pages.Test3Model
@using Microsoft.Extensions.Options
@using SampleApp.Models
@inject IOptions<MyOptions> optionsAccessor


<p><b>Option1:</b> @optionsAccessor.Value.Option1</p>
<p><b>Option2:</b> @optionsAccessor.Value.Option2</p>

存取 MVC 檢視檔案中的設定

下列程式碼會顯示 MVC 檢視中的設定資料:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

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

存取 Program.cs 中的設定

下列程式碼會存取 Program.cs 檔案中的設定。

var builder = WebApplication.CreateBuilder(args);

var key1 = builder.Configuration.GetValue<string>("KeyOne");

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

var key2 = app.Configuration.GetValue<int>("KeyTwo");
var key3 = app.Configuration.GetValue<bool>("KeyThree");

app.Logger.LogInformation("KeyOne: {KeyOne}", key1);
app.Logger.LogInformation("KeyTwo: {KeyTwo}", key2);
app.Logger.LogInformation("KeyThree: {KeyThree}", key3);

app.Run();

在上述範例的 appsettings.json

{
  ...
  "KeyOne": "Key One Value",
  "KeyTwo": 1999,
  "KeyThree": true
}

使用委派設定選項

在委派中設定的選項會覆寫在設定提供者中設定的值。

在下列程式碼中,IConfigureOptions<TOptions> 服務會新增至服務容器。 其使用委派為 MyOptions 設定值:

using SampleApp.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<MyOptions>(myOptions =>
{
    myOptions.Option1 = "Value configured in delegate";
    myOptions.Option2 = 500;
});

var app = builder.Build();

下列程式碼會顯示選項值:

public class Test2Model : PageModel
{
    private readonly IOptions<MyOptions> _optionsDelegate;

    public Test2Model(IOptions<MyOptions> optionsDelegate )
    {
        _optionsDelegate = optionsDelegate;
    }

    public ContentResult OnGet()
    {
        return Content($"Option1: {_optionsDelegate.Value.Option1} \n" +
                       $"Option2: {_optionsDelegate.Value.Option2}");
    }
}

在上述範例中,Option1Option2 的值已在 appsettings.json 中指定,然後會由已設定的委派覆寫。

主機與應用程式組態的比較

設定及啟動應用程式之前,會先設定及啟動「主機」。 主機負責應用程式啟動和存留期管理。 應用程式與主機都是使用此主題中所述的設定提供者來設定的。 主機組態機碼/值組也會包含在應用程式的組態中。 如需建置主機時如何使用設定提供者,以及設定來源如何影響主機設定的詳細資訊,請參閱 ASP.NET Core 基本概念的概觀 (部分機器翻譯)。

預設主機設定

如需使用 Web 主機時預設組態的詳細資料,請參閱本主題的 ASP.NET Core 2.2 版本

  • 主機組態的提供來源:
  • 已建立 Web 主機預設組態 (ConfigureWebHostDefaults):
    • Kestrel 會用作為網頁伺服器,並使用應用程式的設定提供者來設定。
    • 新增主機篩選中介軟體。
    • 如果 ASPNETCORE_FORWARDEDHEADERS_ENABLED 環境變數設定為 true,則會新增轉接的標頭中介軟體。
    • 啟用 IIS 整合。

其他設定

此主題僅適用於應用程式設定。 執行及裝載 ASP.NET Core 應用程式的其他方面是使用此主題中未涵蓋的設定檔所設定:

launchSettings.json 中設定的環境變數會覆寫系統環境中設定的環境變數。

如需從舊版 ASP.NET 移轉應用程式設定的詳細資訊,請參閱從 ASP.NET 更新至 ASP.NET Core

從外部組件新增設定

IHostingStartup 實作允許在啟動時從應用程式 Startup 類別外部的外部組件,針對應用程式新增增強功能。 如需詳細資訊,請參閱在 ASP.NET Core 中使用裝載啟動組件 (部分機器翻譯)。

其他資源

ASP.NET Core 中的應用程式設定是使用一或多個設定提供者來執行的。 設定提供者會使用各種設定來源從機碼值組中讀取設定資料:

  • 設定檔案,例如 appsettings.json
  • 環境變數
  • Azure Key Vault
  • Azure 應用程式組態
  • 命令列引數
  • 自訂提供者 (已安裝或已建立)
  • 目錄檔案
  • 記憶體內部 .NET 物件

此文章提供 ASP.NET Core 中的設定相關資訊。 如需在主控台應用程式中使用設定的相關資訊,請參閱 .NET 設定

應用程式與主機設定

ASP.NET Core 應用程式會設定並啟動「主機」。 主機負責應用程式啟動和存留期管理。 ASP.NET Core 範本會建立包含主機的 WebApplicationBuilder。 雖然某些設定可在主機與應用程式設定提供者中完成,但一般只有主機所需的設定應該在主機設定中完成。

應用程式設定具有最高優先順序,我們將在下一節中詳述。 主機設定遵循應用程式設定,而且已在此文章中描述。

預設應用程式設定來源

使用 dotnet new 或 Visual Studio 建立的 ASP.NET Core Web 應用程式會產生下列程式碼:

var builder = WebApplication.CreateBuilder(args);

WebApplication.CreateBuilder 會初始化具有預先設定之預設值的之 WebApplicationBuilder 類別的新執行個體。 已初始化的 WebApplicationBuilder (builder) 會以下列順序為應用程式提供下列設定 (從最高到最低優先順序):

  1. 使用命令列設定提供者的命令列引數。
  2. 使用未附加前置詞之環境變數設定提供者的未附加前置詞之環境變數。
  3. 應用程式在 Development 環境中執行時的使用者密碼
  4. 使用 JSON 設定提供者appsettings.{Environment}.json。 例如,appsettings.Production.jsonappsettings.Development.json
  5. 使用 JSON 設定提供者appsettings.json
  6. 使用下一節所述的主機設定來遞補。

預設主機設定來源

下列清單包含預設主機設定來源 (從最高到最低優先順序):

  1. 使用環境變數設定提供者且具有 ASPNETCORE_ 前置詞的環境變數。
  2. 使用命令列設定提供者的命令列引數
  3. 使用環境變數設定提供者且具有 DOTNET_ 前置詞的環境變數。

當在主機與應用程式中設定設定值時,會使用應用程式設定。

請參閱此 GitHub 註解中的說明,以取得為何具有 ASPNETCORE_ 前置詞的環境變數在主機設定中具有比命令列引數高之優先順序的說明。

主機變數

下列變數已在主機建立器初始化期間的早期鎖定,而且不會受應用程式設定影響:

每個其他主機設定都是從應用程式設定而非主機設定中讀取。

URLS 是不屬於啟動程序設定的許多常見主機設定之一。 就像不存在於先前清單中的每個其他主機設定一樣,稍後會從應用程式設定讀取 URLS。主機設定是應用程式設定的後援,因此主機設定可用來設定 URLS,但其將由應用程式設定中的任何設定來源 (如 appsettings.json) 覆寫。

如需詳細資訊,請參閱變更內容根目錄、應用程式名稱和環境 (部分機器翻譯) 與依環境變數或命令列變更內容根目錄、應用程式名稱和環境 (部分機器翻譯)

此文章中的剩餘小節指的是應用程式設定。

應用程式設定提供者

下列程式碼會依照設定提供者的新增順序顯示已啟用的設定提供者:

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() + "\n";
        }

        return Content(str);
    }
}

前面的最高到最低優先順序預設設定來源清單以提供者新增至範本產生之應用程式的相反順序顯示提供者。 例如,JSON 設定提供者是在命令列設定提供者之前新增。

後面新增的設定提供者具有較高的優先順序,而且會覆寫先前的機碼設定。 例如,若同時在 appsettings.json 與環境中設定 MyKey,將會使用環境值。 使用預設設定提供者,命令列設定提供者會覆寫所有其他提供者。

如需有關 CreateBuilder 的詳細資訊,請參閱預設建立器設定 (部分機器翻譯)。

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": "*"
}

來自範例下載的下列程式碼會顯示數個上述組態設定:

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

預設的 JsonConfigurationProvider 會以下列順序載入設定:

  1. appsettings.json
  2. appsettings.{Environment}.json:例如,appsettings.Production.jsonappsettings.Development.json 檔案。 檔案的環境版本是以 IHostingEnvironment.EnvironmentName 為基礎來載入的。 如需詳細資訊,請參閱在 ASP.NET Core 中使用多個環境 (部分機器翻譯)。

appsettings.{Environment}.json 值會覆寫 appsettings.json 中的機碼。 例如,根據預設:

  • 在開發環境中,appsettings.Development.json 設定會覆寫在 appsettings.json 中找到的值。
  • 在生產環境中,appsettings.Production.json 設定會覆寫在 appsettings.json 中找到的值。 例如,將應用程式部署到 Azure 時。

若必須保證設定值,請參閱 GetValue (部分機器翻譯)。 上述範例只會讀取字串,而且不支援預設值。

使用預設設定,appsettings.jsonappsettings.{Environment}.json 檔案會使用 reloadOnChange: true 來啟用。 在應用程式啟動之後appsettings.jsonappsettings.{Environment}.json 檔案所做的變更會由 JSON 設定提供者讀取。

使用選項模式繫結階層式設定資料

讀取相關設定值的慣用方式是使用選項模式 (部分機器翻譯)。 例如,為讀取下列設定值:

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

建立下列 PositionOptions 類別:

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

    public string Title { get; set; } = String.Empty;
    public string Name { get; set; } = String.Empty;
}

選項類別:

  • 必須為非抽象,且具有公用的無參數建構函式。
  • 型別的所有公用讀取/寫入屬性都會繫結。
  • 欄位繫結。 在上述程式碼中,Position 未繫結: 會使用 Position 欄位,因此當您將類別繫結到設定提供者時,不需要以硬式編碼方式將字串 "Position" 放在應用程式中。

下列程式碼範例:

  • 呼叫 ConfigurationBinder.Bind 以將 PositionOptions 類別繫結到 Position 區段。
  • 顯示 Position 設定資料。
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} \n" +
                       $"Name: {positionOptions.Name}");
    }
}

在上述程式碼中,根據預設值,會讀取在應用程式啟動之後對 JSON 設定檔所做的變更。

ConfigurationBinder.Get<T> 會繫結並傳回指定的型別。 ConfigurationBinder.Get<T> 可能比使用 ConfigurationBinder.Bind 還方便。 下列程式碼會示範如何搭配 PositionOptions 類別使用 ConfigurationBinder.Get<T>

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} \n" +
                       $"Name: {positionOptions.Name}");
    }
}

在上述程式碼中,根據預設值,會讀取在應用程式啟動之後對 JSON 設定檔所做的變更。

使用選項模式的替代方式是繫結 Position 區段並將其新增至相依性插入服務容器。 在下列程式碼中,PositionOptions 會使用 Configure 新增到服務容器,並繫結到設定:

using ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<PositionOptions>(
    builder.Configuration.GetSection(PositionOptions.Position));

var app = builder.Build();

使用上述程式碼,下列程式碼會讀取位置選項:

public class Test2Model : PageModel
{
    private readonly PositionOptions _options;

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

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

在上述程式碼中,不會讀取在應用程式啟動之後對 JSON 設定檔所做的變更。 若要讀取在應用程式啟動之後所做的變更,請使用 IOptionsSnapshot

使用預設設定,appsettings.jsonappsettings.{Environment}.json 檔案會使用 reloadOnChange: true 來啟用。 在應用程式啟動之後appsettings.jsonappsettings.{Environment}.json 檔案所做的變更會由 JSON 設定提供者讀取。

如需有關新增其他 JSON 設定檔的資訊,請參閱此文件中的 JSON 設定提供者

結合服務集合

請考量會註冊服務並設定選項的下列內容:

using ConfigSample.Options;
using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<PositionOptions>(
    builder.Configuration.GetSection(PositionOptions.Position));
builder.Services.Configure<ColorOptions>(
    builder.Configuration.GetSection(ColorOptions.Color));

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

var app = builder.Build();

相關註冊群組可移至擴充方法,以註冊服務。 例如,設定服務會新增至下列類別:

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

        public static IServiceCollection AddMyDependencyGroup(
             this IServiceCollection services)
        {
            services.AddScoped<IMyDependency, MyDependency>();
            services.AddScoped<IMyDependency2, MyDependency2>();

            return services;
        }
    }
}

剩餘的服務會類似的類別中註冊。 下列程式碼使用新增擴充方法來註冊服務:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services
    .AddConfig(builder.Configuration)
    .AddMyDependencyGroup();

builder.Services.AddRazorPages();

var app = builder.Build();

注意:每個 services.Add{GROUP_NAME} 擴充方法都會新增並可能會設定服務。 例如,AddControllersWithViews 會新增具有所要求檢視的服務 MVC 控制器,而 AddRazorPages 會新增 Razor Pages 所要求的服務。

安全性與使用者祕密

設定資料方針:

  • 永遠不要將密碼或其他敏感性資料儲存在設定提供者程式碼或純文字設定檔中。 祕密管理員工具可以用來儲存開發環境中的密碼。
  • 不要在開發或測試環境中使用生產環境祕密。
  • 請在專案外部指定祕密,以防止其意外認可至開放原始碼存放庫。

根據預設,使用者祕密設定來源會在 JSON 設定來源之後註冊。 因此,使用者祕密金鑰的優先順序高於 appsettings.jsonappsettings.{Environment}.json 中金鑰的優先順序。

如需有關儲存密碼或其他敏感性資料的詳細資訊:

Azure Key Vault 可安全地儲存 ASP.NET Core 應用程式的應用程式祕密。 如需詳細資訊,請參閱 ASP.NET Core 中的 Azure Key Vault 設定提供者 (部分機器翻譯)。

未附加前置詞的環境變數

未附加前置詞之環境變數指的是那些已附加 ASPNETCORE_DOTNET_ 前置詞之環境變數以外的環境變數。 例如,ASP.NET Core Web 應用程式範本會在 launchSettings.json 中設定 "ASPNETCORE_ENVIRONMENT": "Development"。 如需有關 ASPNETCORE_DOTNET_ 環境變數的詳細資訊,請參閱:

使用預設設定,EnvironmentVariablesConfigurationProvider 會在讀取 appsettings.jsonappsettings.{Environment}.json使用者祕密後,從環境變數機碼值組載入設定。 因此,從環境讀取的機碼值會覆寫從 appsettings.jsonappsettings.{Environment}.json 與使用者祕密讀取的值。

: 分隔符號不適用於所有平台上的環境變數階層式機碼。 __,雙底線,為:

  • 所有平台都支援。 例如,Bash 不支援 : 分隔符號,但支援 __
  • 自動由 : 取代

下列 set 命令:

  • 在 Windows 上設定上述範例的環境機碼與值。
  • 使用範例下載時測試設定。 dotnet run 命令必須在專案目錄中執行。
set MyKey="My key from Environment"
set Position__Title=Environment_Editor
set Position__Name=Environment_Rick
dotnet run

上述環境設定:

  • 只會在從其所設定命令視窗啟動的處理序中進行設定。
  • 將不會由使用 Visual Studio 啟動的瀏覽器讀取。

下列 setx 命令也可用來在 Windows 上設定環境機碼與值。 不同於 setsetx 設定會予以保存。 /M 會在系統環境中設定該變數。 如果未使用 /M 切換開關,則會設定使用者環境變數。

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

測試上述命令是否會覆寫 appsettings.jsonappsettings.{Environment}.json

  • 使用 Visual Studio:結束並重新啟動 Visual Studio。
  • 使用 CLI:啟動新的命令視窗,然後輸入 dotnet run

使用字串呼叫 AddEnvironmentVariables,以指定環境變數的前置詞:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Configuration.AddEnvironmentVariables(prefix: "MyCustomPrefix_");

var app = builder.Build();

在上述程式碼中:

  • builder.Configuration.AddEnvironmentVariables(prefix: "MyCustomPrefix_") 會在預設設定提供者之後新增。 如需有關排定設定提供者優先順序的範例,請參閱 JSON 設定提供者
  • 使用 MyCustomPrefix_ 前置詞設定的環境變數會覆寫預設設定提供者。 這包括沒有前置詞的環境變數。

讀取設定機碼值組時,會移除前置詞。

下列命令會測試自訂前置詞:

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

預設設定會載入具有 DOTNET_ASPNETCORE_ 前置詞的環境變數與命令列引數。 ASP.NET Core 會為主機與應用程式設定使用 DOTNET_ASPNETCORE_ 前置詞,但不會為使用者設定使用。 如需主機與應用程式設定的詳細資訊,請參閱 .NET 泛型主機 (部分機器翻譯)。

Azure App Service 上,選取 [設定] > [組態] 頁面上的 [新增應用程式設定]。 Azure App Service 應用程式設定為:

  • 在待用及透過加密通道傳輸時加密。
  • 公開為環境變數。

如需詳細資訊,請參閱 Azure App:使用 Azure 入口網站覆寫應用程式設定

如需 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"
        }
    ]
}

環境變數

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 範本會產生 launchSettings.json 檔案,此檔案會將端點設定設定為:

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

設定 applicationUrl 會設定 ASPNETCORE_URLS 環境變數並覆寫環境中設定的值。

在 Linux 上逸出環境變數

在 Linux 上,必須逸出 URL 環境變數的值,systemd 才能加以剖析。 使用 Linux 工具 systemd-escape,這會得到 http:--localhost:5001

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

顯示環境變數

下列程式碼會在應用程式啟動時顯示環境變數與值,這在針對環境設定進行偵錯時很有幫助:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

foreach (var c in builder.Configuration.AsEnumerable())
{
    Console.WriteLine(c.Key + " = " + c.Value);
}

命令列

使用預設設定,CommandLineConfigurationProvider 會在下列設定來源之後,從命令列引數機碼值組載入設定:

  • appsettings.jsonappsettings.{Environment}.json 檔案。
  • 開發環境中的應用程式祕密
  • 環境變數。

根據預設,在命令列上設定的設定值會覆寫使用所有其他設定提供者設定的設定值。

命令列引數

下列命令會使用 = 設定機碼與值:

dotnet run MyKey="Using =" 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

機碼值:

  • 必須跟在 = 後面,或當值後面接著空格時,機碼必須有 --/ 前置詞。
  • 如果使用 =,則不是必要項。 例如: MySetting=

在相同的命令中,請不要混用使用 = 的命令列引數機碼值組與使用空格的機碼值組。

切換對應

參數對應允許機碼名稱取代邏輯。 將切換取代的字典提供給 AddCommandLine 方法。

使用切換對應字典時,會檢查字典中是否有任何索引鍵符合命令列引數所提供的索引鍵。 如果在字典中找到命令列機碼,則會傳回字典值以在應用程式的設定中設定機碼值組。 所有前面加上單虛線 (-) 的命令列索引鍵都需要切換對應。

切換對應字典索引鍵規則:

  • 切換的開頭必須是 ---
  • 切換對應字典不能包含重複索引鍵。

若要使用切換對應字典,請將其傳遞到對 AddCommandLine 的呼叫中:


var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

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

builder.Configuration.AddCommandLine(args, switchMappings);

var app = builder.Build();

執行下列命令工作以測試機碼取代:

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

下列程式碼顯示已取代屬性的機碼值:

public class Test3Model : PageModel
{
    private readonly IConfiguration Config;

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

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

針對使用切換對應的應用程式,呼叫 CreateDefaultBuilder 不應傳遞引數。 CreateDefaultBuilder 方法的 AddCommandLine 呼叫不包括對應的切換,且沒有任何方式可以將切換對應字典傳遞給 CreateDefaultBuilder。 解決方式並非將引數傳遞給 CreateDefaultBuilder,而是允許 ConfigurationBuilder 方法的 AddCommandLine 方法同時處理引數與切換對應字典。

使用 Visual Studio 設定環境與命令列引數

您可以在 Visual Studio 中從啟動設定檔對話方塊設定環境與命令列引數:

  • 在 [方案總管] 中,以滑鼠右鍵按一下專案,然後選取 [屬性]
  • 選取 [偵錯] > [一般] 索引標籤,然後選取 [開啟偵錯啟動設定檔 UI]

階層式設定資料

設定 API 可透過在設定機碼中使用分隔符號來壓平合併階層式資料,以讀取階層式設定資料。

範例下載包含下列 appsettings.json 檔案:

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

來自範例下載的下列程式碼會顯示數個組態設定:

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

讀取階層式設定資料的慣用方式是使用選項模式。 如需詳細資訊,請參閱此文件中的繫結階層式設定資料

GetSectionGetChildren 方法可用來在設定資料中隔離區段與區段的子系。 GetSection,、 GetChildren 與 Exists 中說明這些方法。

設定機碼與值

設定機碼:

  • 不區分大小寫。 例如,ConnectionStringconnectionstring 會視為對等機碼。
  • 若已在多個設定提供者中設定機碼與值,會使用來自最後一個新增之提供者的值。 如需詳細資訊,請參閱預設設定
  • 階層式機碼
    • 在設定 API 內,冒號分隔字元 (:) 可在所有平台上運作。
    • 在環境變數中,冒號分隔字元可能無法在所有平台上運作。 所有平台都支援雙底線 (__),且雙底線會自動轉換為冒號 :
    • 在 Azure Key Vault 中,階層式機碼使用 -- 作為分隔符號。 在祕密載入到應用程式的設定時,Azure Key Vault 設定提供者會自動將 -- 取代為 :
  • ConfigurationBinder 支援在設定機碼中使用陣列索引將陣列繫結到物件。 將陣列繫結到類別一節說明陣列繫結。

設定值:

  • 為字串。
  • Null 值無法存放在設定中或繫結到物件。

設定提供者

下表顯示可供 ASP.NET Core 應用程式使用的設定提供者。

Provider 從提供設定
Azure Key Vault 組態提供者 Azure Key Vault
Azure 應用程式設定提供者 Azure 應用程式組態
命令列設定提供者 命令列參數
自訂設定提供者 自訂來源
環境變數設定提供者 環境變數
檔案設定提供者 INI、JSON 與 XML 檔案
每個檔案機碼設定提供者 目錄檔案
記憶體設定提供者 記憶體內集合
使用者祕密 使用者設定檔目錄中的檔案

系統會依照設定來源的設定提供者的指定順序讀入設定來源。 在您的程式碼中針對應用程式所需之底層設定來源的優先順序,為設定提供者排序。

典型的設定提供者順序是:

  1. appsettings.json
  2. appsettings.{Environment}.json
  3. 使用者祕密
  4. 使用環境變數設定提供者的環境變數。
  5. 使用命令列設定提供者的命令列引數。

將命令列設定提供者新增到提供者序列結尾,以讓命令列引數覆寫由其他提供者所設定的設定是常見做法。

上述提供者序列用於預設設定

連接字串前置詞

設定 API 具有四個連接字串環境變數的特殊處理規則。 這些連接字串涉及為應用程式環境設定 Azure 連接字串。 資料表中所顯示具有前置詞的環境變數會使用預設設定載入應用程式,或是當未提供任何前置詞給 AddEnvironmentVariables 時。

連接字串前置詞 Provider
CUSTOMCONNSTR_ 自訂提供者
MYSQLCONNSTR_ MySQL
SQLAZURECONNSTR_ Azure SQL Database
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 是用於從檔案系統載入設定的基底類別。 下列設定提供者衍生自 FileConfigurationProvider

INI 設定提供者

IniConfigurationProvider 會在執行階段從 INI 檔案機碼值組載入設定。

下列程式碼會新增數個設定提供者:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddIniFile("MyIniConfig.ini", optional: true, reloadOnChange: true)
    .AddIniFile($"MyIniConfig.{builder.Environment.EnvironmentName}.ini",
                optional: true, reloadOnChange: true);

builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

在上述程式碼中,MyIniConfig.iniMyIniConfig.{Environment}.ini 檔案中的設定已由下列項目中的設定覆寫:

範例下載包含下列 MyIniConfig.ini 檔案:

MyKey="MyIniConfig.ini Value"

[Position]
Title="My INI Config title"
Name="My INI Config name"

[Logging:LogLevel]
Default=Information
Microsoft=Warning

來自範例下載的下列程式碼會顯示數個上述組態設定:

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

JSON 設定提供者

JsonConfigurationProvider 會從 JSON 檔案機碼值組載入設定。

多載可以指定:

  • 檔案是否為選擇性。
  • 檔案變更時是否要重新載入設定。

請考慮下列程式碼:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddJsonFile("MyConfig.json",
        optional: true,
        reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

上述 程式碼:

  • 使用下列選項設定 JSON 設定提供者以載入 MyConfig.json 檔案:
    • optional: true:檔案為選擇性。
    • reloadOnChange: true:儲存變更時會重新載入該檔案。
  • MyConfig.json 檔案之前讀取預設設定提供者MyConfig.json 檔案中的設定會覆寫預設設定提供者 (包括環境變數設定提供者命令列設定提供者) 中的設定。

您通常想讓自訂 JSON 檔案覆寫環境變數設定提供者命令列設定提供者中設定的值。

XML 設定提供者

XmlConfigurationProvider 會在執行階段從 XML 檔案機碼值組載入設定。

下列程式碼會新增數個設定提供者:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddXmlFile("MyXMLFile.xml", optional: true, reloadOnChange: true)
    .AddXmlFile($"MyXMLFile.{builder.Environment.EnvironmentName}.xml",
                optional: true, reloadOnChange: true);

builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

在上述程式碼中,MyXMLFile.xmlMyXMLFile.{Environment}.xml 檔案中的設定已由下列項目中的設定覆寫:

範例下載包含下列 MyXMLFile.xml 檔案:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <MyKey>MyXMLFile Value</MyKey>
  <Position>
    <Title>Title from  MyXMLFile</Title>
    <Name>Name from MyXMLFile</Name>
  </Position>
  <Logging>
    <LogLevel>
      <Default>Information</Default>
      <Microsoft>Warning</Microsoft>
    </LogLevel>
  </Logging>
</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

每個檔案機碼設定提供者

KeyPerFileConfigurationProvider 使用目錄的檔案做為設定機碼值組。 機碼是檔案名稱。 值包含檔案的內容。 每個檔案機碼設定提供者是在 Docker 裝載案例中使用。

若要啟用每個檔案機碼設定,請在 ConfigurationBuilder 的執行個體上呼叫 AddKeyPerFile 延伸模組方法。 檔案的 directoryPath 必須是絕對路徑。

多載允許指定:

  • 設定來源的 Action<KeyPerFileConfigurationSource> 委派。
  • 目錄是否為選擇性與目錄的路徑。

雙底線 (__) 是做為檔案名稱中的設定金鑰分隔符號使用。 例如,檔案名稱 Logging__LogLevel__System 會產生設定金鑰 Logging:LogLevel:System

建置主機時呼叫 ConfigureAppConfiguration 以指定應用程式的設定:

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

記憶體設定提供者

MemoryConfigurationProvider 使用記憶體內集合做為設定機碼值組。

下列程式碼會將記憶體收集新增至設定系統:

var builder = WebApplication.CreateBuilder(args);

var Dict = new Dictionary<string, string>
        {
           {"MyKey", "Dictionary MyKey Value"},
           {"Position:Title", "Dictionary_Title"},
           {"Position:Name", "Dictionary_Name" },
           {"Logging:LogLevel:Default", "Warning"}
        };

builder.Configuration.AddInMemoryCollection(Dict);
builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

來自範例下載的下列程式碼會顯示上述組態設定:

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 設定提供者

如需另一個使用 MemoryConfigurationProvider 的範例,請參閱繫結陣列

Kestrel 端點設定

Kestrel 特定端點設定會覆寫所有跨伺服器端點設定。 跨伺服器端點設定包括:

請考慮 ASP.NET Core Web 應用程式中使用的下列 appsettings.json 檔案。

{
  "Kestrel": {
    "Endpoints": {
      "Https": {
        "Url": "https://localhost:9999"
      }
    }
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
} 

當上述反白顯示的標記用於 ASP.NET Core Web 應用程式應用程式從命令列使用下列跨伺服器端點設定啟動時:

dotnet run --urls="https://localhost:7777"

Kestrel 會繫結到特別針對 appsettings.json 檔案 (https://localhost:9999) 而非 https://localhost:7777 中的 Kestrel 設定的端點。

請考慮設定為環境變數的 Kestrel 特定端點:

set Kestrel__Endpoints__Https__Url=https://localhost:8888

在上述環境變數中,Https 是 Kestrel 特定端點的名稱。 上述 appsettings.json 檔案也定義名為 Https 的 Kestrel 特定端點。 根據預設,使用環境變數設定提供者的環境變數會在 appsettings.{Environment}.json 之後讀取,因此會針對 Https 端點使用上述環境變數。

GetValue

ConfigurationBinder.GetValue 會從具有所指定機碼的設定擷取單一值,並將其轉換為指定的型別:

public class TestNumModel : PageModel
{
    private readonly IConfiguration Configuration;

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

    public ContentResult OnGet()
    {
        var number = Configuration.GetValue<int>("NumberKey", 99);
        return Content($"{number}");
    }
}

在上述程式碼中,若在設定中找不到 NumberKey,則會使用預設值 99

GetSection、GetChildren 與 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 新增到設定提供者:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddJsonFile("MySubsection.json",
                 optional: true,
                 reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

GetSection

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 與 Exists

下列程式碼會呼叫 IConfiguration.GetChildren 並傳回 section2:subsection0 的值:

public class TestSection4Model : PageModel
{
    private readonly IConfiguration Config;

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

    public ContentResult OnGet()
    {
        string s = "";
        var selection = Config.GetSection("section2");
        if (!selection.Exists())
        {
            throw new 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 以確認區段是否存在:

繫結陣列

ConfigurationBinder.Bind 支援在設定機碼中使用陣列索引將陣列繫結到物件。 任何公開數值機碼區段的陣列格式都能以陣列方式繫結到 POCO 類別陣列。

考慮來自範例下載MyArray.json

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

下列程式碼會將 MyArray.json 新增到設定提供者:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddJsonFile("MyArray.json",
                 optional: true,
                 reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

下列程式碼會讀取設定並顯示值:

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>();
        if (_array == null)
        {
            throw new ArgumentNullException(nameof(_array));
        }
        string s = String.Empty;

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

        return Content(s);
    }
}
public class ArrayExample
{
    public string[]? Entries { get; set; } 
}

上述程式碼會傳回下列輸出:

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 項目。

自訂設定提供者

範例應用程式示範如何建立會使用 Entity Framework (EF) 從資料庫讀取設定機碼值組的基本設定提供者。

提供者具有下列特性:

  • EF 記憶體內資料庫會用於示範用途。 若要使用需要連接字串的資料庫,請實作第二個 ConfigurationBuilder 以從另一個設定提供者提供連接字串。
  • 啟動時,該提供者會將資料庫資料表讀入到設定中。 該提供者不會以個別機碼為基礎查詢資料庫。
  • 未實作變更時重新載入,因此在應用程式啟動後更新資料庫對應用程式設定沒有影響。

定義 EFConfigurationValue 實體來在資料庫中存放設定值。

Models/EFConfigurationValue.cs

public class EFConfigurationValue
{
    public string Id { get; set; } = String.Empty;
    public string Value { get; set; } = String.Empty;
}

新增 EFConfigurationContext 以存放及存取已設定的值。

EFConfigurationProvider/EFConfigurationContext.cs

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

    public DbSet<EFConfigurationValue> Values => Set<EFConfigurationValue>();
}

建立會實作 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) => new EFConfigurationProvider(_optionsAction);
}

透過繼承自 ConfigurationProvider 來建立自訂設定提供者。 若資料庫是空的,設定提供者會初始化資料庫。 因為設定機碼不區分大小寫,所以會使用不區分大小寫的比較子 (StringComparer.OrdinalIgnoreCase) 來建立用來初始化資料庫的字典。

EFConfigurationProvider/EFConfigurationProvider.cs

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

    Action<DbContextOptionsBuilder> OptionsAction { get; }

    public override void Load()
    {
        var builder = new DbContextOptionsBuilder<EFConfigurationContext>();

        OptionsAction(builder);

        using (var dbContext = new EFConfigurationContext(builder.Options))
        {
            if (dbContext == null || dbContext.Values == null)
            {
                throw new Exception("Null DB context");
            }
            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-2005
        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." }
            };

        if (dbContext == null || dbContext.Values == null)
        {
            throw new Exception("Null DB context");
        }

        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

//using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddEFConfiguration(
    opt => opt.UseInMemoryDatabase("InMemoryDb"));

var app = builder.Build();

app.Run();

使用相依性插入 (DI) 來存取設定

可以透過解析 IConfiguration 服務,使用相依性插入 (DI) 將設定插入到服務:

public class Service
{
    private readonly IConfiguration _config;

    public Service(IConfiguration config) =>
        _config = config;

    public void DoSomething()
    {
        var configSettingValue = _config["ConfigSetting"];

        // ...
    }
}

如需有關如何使用 IConfiguration 存取值的詳細資訊,請參閱此文章中的 GetValueGetSection、GetChildren 與 Exists

存取 Razor Pages 中的設定

下列程式碼會顯示 Razor Pages 中的設定資料:

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

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

在下列程式碼中,MyOptions 會使用 Configure 新增到服務容器,並繫結到設定:

using SampleApp.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<MyOptions>(
    builder.Configuration.GetSection("MyOptions"));

var app = builder.Build();

下列標記使用 @injectRazor 指示詞來解析及顯示選項值:

@page
@model SampleApp.Pages.Test3Model
@using Microsoft.Extensions.Options
@using SampleApp.Models
@inject IOptions<MyOptions> optionsAccessor


<p><b>Option1:</b> @optionsAccessor.Value.Option1</p>
<p><b>Option2:</b> @optionsAccessor.Value.Option2</p>

存取 MVC 檢視檔案中的設定

下列程式碼會顯示 MVC 檢視中的設定資料:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

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

存取 Program.cs 中的設定

下列程式碼會存取 Program.cs 檔案中的設定。

var builder = WebApplication.CreateBuilder(args);

var key1 = builder.Configuration.GetValue<string>("KeyOne");

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

var key2 = app.Configuration.GetValue<int>("KeyTwo");
var key3 = app.Configuration.GetValue<bool>("KeyThree");

app.Logger.LogInformation("KeyOne: {KeyOne}", key1);
app.Logger.LogInformation("KeyTwo: {KeyTwo}", key2);
app.Logger.LogInformation("KeyThree: {KeyThree}", key3);

app.Run();

在上述範例的 appsettings.json

{
  ...
  "KeyOne": "Key One Value",
  "KeyTwo": 1999,
  "KeyThree": true
}

使用委派設定選項

在委派中設定的選項會覆寫在設定提供者中設定的值。

在下列程式碼中,IConfigureOptions<TOptions> 服務會新增至服務容器。 其使用委派為 MyOptions 設定值:

using SampleApp.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<MyOptions>(myOptions =>
{
    myOptions.Option1 = "Value configured in delegate";
    myOptions.Option2 = 500;
});

var app = builder.Build();

下列程式碼會顯示選項值:

public class Test2Model : PageModel
{
    private readonly IOptions<MyOptions> _optionsDelegate;

    public Test2Model(IOptions<MyOptions> optionsDelegate )
    {
        _optionsDelegate = optionsDelegate;
    }

    public ContentResult OnGet()
    {
        return Content($"Option1: {_optionsDelegate.Value.Option1} \n" +
                       $"Option2: {_optionsDelegate.Value.Option2}");
    }
}

在上述範例中,Option1Option2 的值已在 appsettings.json 中指定,然後會由已設定的委派覆寫。

主機與應用程式組態的比較

設定及啟動應用程式之前,會先設定及啟動「主機」。 主機負責應用程式啟動和存留期管理。 應用程式與主機都是使用此主題中所述的設定提供者來設定的。 主機組態機碼/值組也會包含在應用程式的組態中。 如需建置主機時如何使用設定提供者,以及設定來源如何影響主機設定的詳細資訊,請參閱 ASP.NET Core 基本概念的概觀 (部分機器翻譯)。

預設主機設定

如需使用 Web 主機時預設組態的詳細資料,請參閱本主題的 ASP.NET Core 2.2 版本

  • 主機組態的提供來源:
  • 已建立 Web 主機預設組態 (ConfigureWebHostDefaults):
    • Kestrel 會用作為網頁伺服器,並使用應用程式的設定提供者來設定。
    • 新增主機篩選中介軟體。
    • 如果 ASPNETCORE_FORWARDEDHEADERS_ENABLED 環境變數設定為 true,則會新增轉接的標頭中介軟體。
    • 啟用 IIS 整合。

其他設定

此主題僅適用於應用程式設定。 執行及裝載 ASP.NET Core 應用程式的其他方面是使用此主題中未涵蓋的設定檔所設定:

launchSettings.json 中設定的環境變數會覆寫系統環境中設定的環境變數。

如需從舊版 ASP.NET 移轉應用程式設定的詳細資訊,請參閱從 ASP.NET 更新至 ASP.NET Core

從外部組件新增設定

IHostingStartup 實作允許在啟動時從應用程式 Startup 類別外部的外部組件,針對應用程式新增增強功能。 如需詳細資訊,請參閱在 ASP.NET Core 中使用裝載啟動組件 (部分機器翻譯)。

其他資源

Kestrel 端點設定

Kestrel 特定端點設定會覆寫所有跨伺服器端點設定。 跨伺服器端點設定包括:

請考慮 ASP.NET Core Web 應用程式中使用的下列 appsettings.json 檔案。

{
  "Kestrel": {
    "Endpoints": {
      "Https": {
        "Url": "https://localhost:9999"
      }
    }
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
} 

當上述反白顯示的標記用於 ASP.NET Core Web 應用程式應用程式從命令列使用下列跨伺服器端點設定啟動時:

dotnet run --urls="https://localhost:7777"

Kestrel 會繫結到特別針對 appsettings.json 檔案 (https://localhost:9999) 而非 https://localhost:7777 中的 Kestrel 設定的端點。

請考慮設定為環境變數的 Kestrel 特定端點:

set Kestrel__Endpoints__Https__Url=https://localhost:8888

在上述環境變數中,Https 是 Kestrel 特定端點的名稱。 上述 appsettings.json 檔案也定義名為 Https 的 Kestrel 特定端點。 根據預設,使用環境變數設定提供者的環境變數會在 appsettings.{Environment}.json 之後讀取,因此會針對 Https 端點使用上述環境變數。

GetValue

ConfigurationBinder.GetValue 會從具有所指定機碼的設定擷取單一值,並將其轉換為指定的型別。 此方法是 IConfiguration 的擴充方法:

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

GetSection

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 與 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 以確認區段是否存在:

繫結陣列

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

下列程式碼會讀取 arrayDictDictionary 中的設定並顯示值:

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.jsonarrayDictDictionary 的設定:

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

自訂設定提供者不需要實作陣列繫結。

自訂設定提供者

範例應用程式示範如何建立會使用 Entity Framework (EF) 從資料庫讀取設定機碼值組的基本設定提供者。

提供者具有下列特性:

  • EF 記憶體內資料庫會用於示範用途。 若要使用需要連接字串的資料庫,請實作第二個 ConfigurationBuilder 以從另一個設定提供者提供連接字串。
  • 啟動時,該提供者會將資料庫資料表讀入到設定中。 該提供者不會以個別機碼為基礎查詢資料庫。
  • 未實作變更時重新載入,因此在應用程式啟動後更新資料庫對應用程式設定沒有影響。

定義 EFConfigurationValue 實體來在資料庫中存放設定值。

Models/EFConfigurationValue.cs

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

新增 EFConfigurationContext 以存放及存取已設定的值。

EFConfigurationProvider/EFConfigurationContext.cs

// using Microsoft.EntityFrameworkCore;

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

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

建立會實作 IConfigurationSource 的類別。

EFConfigurationProvider/EFConfigurationSource.cs

// using Microsoft.EntityFrameworkCore;
// using Microsoft.Extensions.Configuration;

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

// using Microsoft.EntityFrameworkCore;
// using Microsoft.Extensions.Configuration;

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

    Action<DbContextOptionsBuilder> OptionsAction { get; }

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

// using Microsoft.EntityFrameworkCore;
// using Microsoft.Extensions.Configuration;

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

下列程式碼示範如何使用 Program.cs 中的自訂 EFConfigurationProvider

// using Microsoft.EntityFrameworkCore;

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            config.AddEFConfiguration(
                options => options.UseInMemoryDatabase("InMemoryDb"));
        })

存取 [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 中的設定

下列程式碼會顯示 Razor Pages 中的設定資料:

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

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

在下列程式碼中,MyOptions 會使用 Configure 新增到服務容器,並繫結到設定:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<MyOptions>(Configuration.GetSection("MyOptions"));

    services.AddRazorPages();
}

下列標記使用 @injectRazor 指示詞來解析及顯示選項值:

@page
@model SampleApp.Pages.Test3Model
@using Microsoft.Extensions.Options
@inject IOptions<MyOptions> optionsAccessor


<p><b>Option1:</b> @optionsAccessor.Value.Option1</p>
<p><b>Option2:</b> @optionsAccessor.Value.Option2</p>

存取 MVC 檢視檔案中的設定

下列程式碼會顯示 MVC 檢視中的設定資料:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

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

使用委派設定選項

在委派中設定的選項會覆寫在設定提供者中設定的值。

使用委派設定選項已使用範例應用程式中的範例 2 來示範。

在下列程式碼中,IConfigureOptions<TOptions> 服務會新增至服務容器。 其使用委派為 MyOptions 設定值:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<MyOptions>(myOptions =>
    {
        myOptions.Option1 = "Value configured in delegate";
        myOptions.Option2 = 500;
    });

    services.AddRazorPages();
}

下列程式碼會顯示選項值:

public class Test2Model : PageModel
{
    private readonly IOptions<MyOptions> _optionsDelegate;

    public Test2Model(IOptions<MyOptions> optionsDelegate )
    {
        _optionsDelegate = optionsDelegate;
    }

    public ContentResult OnGet()
    {
        return Content($"Option1: {_optionsDelegate.Value.Option1} \n" +
                       $"Option2: {_optionsDelegate.Value.Option2}");
    }
}

在上述範例中,Option1Option2 的值已在 appsettings.json 中指定,然後會由已設定的委派覆寫。

主機與應用程式組態的比較

設定及啟動應用程式之前,會先設定及啟動「主機」。 主機負責應用程式啟動和存留期管理。 應用程式與主機都是使用此主題中所述的設定提供者來設定的。 主機組態機碼/值組也會包含在應用程式的組態中。 如需建置主機時如何使用設定提供者,以及設定來源如何影響主機設定的詳細資訊,請參閱 ASP.NET Core 基本概念的概觀 (部分機器翻譯)。

預設主機設定

如需使用 Web 主機時預設組態的詳細資料,請參閱本主題的 ASP.NET Core 2.2 版本

  • 主機組態的提供來源:
    • 使用環境變數設定提供者且以 DOTNET_ 為前置詞 (例如 DOTNET_ENVIRONMENT) 的環境變數。 載入設定機碼值組時,會移除前置詞 (DOTNET_)。
    • 使用命令列設定提供者的命令列引數。
  • 已建立 Web 主機預設組態 (ConfigureWebHostDefaults):
    • Kestrel 會用作為網頁伺服器,並使用應用程式的設定提供者來設定。
    • 新增主機篩選中介軟體。
    • 如果 ASPNETCORE_FORWARDEDHEADERS_ENABLED 環境變數設定為 true,則會新增轉接的標頭中介軟體。
    • 啟用 IIS 整合。

其他設定

此主題僅適用於應用程式設定。 執行及裝載 ASP.NET Core 應用程式的其他方面是使用此主題中未涵蓋的設定檔所設定:

launchSettings.json 中設定的環境變數會覆寫系統環境中設定的環境變數。

如需從舊版 ASP.NET 移轉應用程式設定的詳細資訊,請參閱從 ASP.NET 更新至 ASP.NET Core

從外部組件新增設定

IHostingStartup 實作允許在啟動時從應用程式 Startup 類別外部的外部組件,針對應用程式新增增強功能。 如需詳細資訊,請參閱在 ASP.NET Core 中使用裝載啟動組件 (部分機器翻譯)。

其他資源