1. 程式人生 > 其它 >ASP.NET Core(十)Configuration 配置優先順序詳解

ASP.NET Core(十)Configuration 配置優先順序詳解

ASP.NET Core 專案啟動,預設執行順序為:宿主 Host -> 讀取配置 -> 日誌設定 -> 註冊服務(DI)-> 新增中介軟體 -> WebHost 監聽 -> 後臺 Work 啟動。

配置的載入和讀取是在啟動流程的最前面。微軟關於 ASP.NET Core 中的配置文件:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/configuration/?view=aspnetcore-6.0

Host.CreateDefaultBuilder 方法中,按照以下順序為應用提供預設配置:

  • ChainedConfigurationProvider:新增現有的 作為源。 在預設配置示例中,新增主機配置,並將它設定為應用配置的第一個源。
  • 使用 appsettings.json的 appsettings.json。
  • 使用 JSON 配置提供程式通過 appsettings..json 提供。 例如,appsettings.Production.json 和 appsettings.Development.json。
  • 應用在 環境中執行時的應用機密。
  • 使用環境變數配置提供程式通過環境變數提供。
  • 使用命令列配置提供程式通過命令列引數提供。

原始碼如下:

public static IHostBuilder CreateDefaultBuilder(string[] args)
        {
            var builder = new HostBuilder();

            builder.UseContentRoot(Directory.GetCurrentDirectory());
            builder.ConfigureHostConfiguration(config =>
            {
                config.AddEnvironmentVariables(prefix: "DOTNET_");
                if (args != null)
                {
                    config.AddCommandLine(args);
                }
            });

            builder.ConfigureAppConfiguration((hostingContext, config) =>
            {
                var env = hostingContext.HostingEnvironment;

                config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                      .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);

                if (env.IsDevelopment() && !string.IsNullOrEmpty(env.ApplicationName))
                {
                    var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
                    if (appAssembly != null)
                    {
                        config.AddUserSecrets(appAssembly, optional: true);
                    }
                }

                config.AddEnvironmentVariables();

                if (args != null)
                {
                    config.AddCommandLine(args);
                }
            })
            .ConfigureLogging((hostingContext, logging) =>
            {
                var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);

                // IMPORTANT: This needs to be added *before* configuration is loaded, this lets
                // the defaults be overridden by the configuration.
                if (isWindows)
                {
                    // Default the EventLogLoggerProvider to warning or above
                    logging.AddFilter<EventLogLoggerProvider>(level => level >= LogLevel.Warning);
                }

                logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
                logging.AddConsole();
                logging.AddDebug();
                logging.AddEventSourceLogger();

                if (isWindows)
                {
                    // Add the EventLogLoggerProvider on windows machines
                    logging.AddEventLog();
                }
            })
            .UseDefaultServiceProvider((context, options) =>
            {
                var isDevelopment = context.HostingEnvironment.IsDevelopment();
                options.ValidateScopes = isDevelopment;
                options.ValidateOnBuild = isDevelopment;
            });

            return builder;
        }

原始碼地址:https://github.com/dotnet/extensions/blob/release/3.1/src/Hosting/Hosting/src/Host.cs

通過程式碼可以看出,程式獲取配置優先順序依次為:appsettings.json -> appsettings.環境.json -> 環境變數 -> 命令列引數。我們根據優先順序進行測試。

新建一個控制檯方法返回所有配置資訊,程式碼如下:

private readonly ILogger<HomeController> _logger;

        public IConfiguration _configuration { get; }

        public HomeController(ILogger<HomeController> logger, IConfiguration configuration)
        {
            _logger = logger;
            _configuration = configuration;
        }

        public IActionResult Index()
        {
            return Json(_configuration.AsEnumerable());
        }

首先,appsettings.json 配置檔案,如下:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "WebConfig": {
    "Name": "itsvse.com",
    "Date": "2021"
  }
}

 新建 appsettings.Test.json 配置,如下:

{
  "WebConfig": {
    "Name": "itsvse.com test"
  }
}

嘗試啟動專案,檢視 WebConfig:Name 和 WebConfig:Date 的配置,如下圖:

找到 Properties -> launchSettings.json 檔案,修改 ASPNETCORE_ENVIRONMENT 環境配置為 Test,如下:

 "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Test"
      }
    }

這時程式會讀取 appsettings.Test.json 的配置,嘗試重新啟動專案,發現 WebConfig:Name 已經覆蓋了,如下圖:

再次修改 launchSettings.json 檔案,通過環境變數設定 WebConfig:Name 的值,程式碼如下:

"IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Test",
        "WebConfig__Name": "itsvse env"
      }
    }

備註:環境變數修改 WebConfig:Name 的值,變數名稱為: WebConfig__Name (中間用雙下劃線隔開

嘗試重啟專案,發現 WebConfig:Name 的值,已經被環境變數設定的值所覆蓋,如下圖:

嘗試通過命令列的形式修改預設配置的值,啟動命令如下:

dotnet run --WebConfig:Name="itsvse command"

如下圖:

用實踐來測試配置鍵值的優先順序,完。