.Net Core ConfigureAppConfiguration 添加额外的资源覆盖环境特定设置

.Net Core ConfigureAppConfiguration adding additional sources overriding environment specific settings

在带有通用主机的 .NET Core 2.1 应用程序中使用 IConfigurationBuilder 时,我配置了 4 个源;但在 ConfigureAppConfiguration 的范围之后有 6 个来源。

在某些时候,我已经加载的 2 个额外源被第二次添加,导致 appsettings.Environment.json 值被隐藏。我还尝试删除 hostsettings.json 配置并验证这不会影响这一点。 这是针对使用 WebjobsSDK 3.0 和 .Net Core 2.1

的 Azure Webjob
    var builder = new HostBuilder()
        .ConfigureHostConfiguration(configurationBuilder =>
        {
             //This is to do some basic host configuration and should only add 2 sources
         configurationBuilder.SetBasePath(Directory.GetCurrentDirectory());
                configurationBuilder.AddJsonFile("hostsettings.json", optional: true);
                configurationBuilder.AddEnvironmentVariables(prefix: "APPSETTING_ASPNETCORE_");
            })
            .ConfigureAppConfiguration((hostContext, configurationBuilder) =>
            {
                //at this point there are 0 sources in the sources
                IHostingEnvironment env = hostContext.HostingEnvironment;
                configurationBuilder.SetBasePath(Directory.GetCurrentDirectory());
                configurationBuilder.AddJsonFile("appSettings.json", optional: false, reloadOnChange: true)
                    .AddJsonFile($"appSettings.{env.EnvironmentName}.json", optional: true,
                        reloadOnChange: true);
                configurationBuilder.AddEnvironmentVariables(prefix: "APPSETTING_ASPNETCORE_");
               //at this point there are 4 sources
            })
            .ConfigureServices((hostContext, servicesCollection) =>
            {
                //now there are 6, 2 additional source that are duplicates
                servicesCollection.Configure<IConfiguration>(hostContext.Configuration);

})

我希望配置提供程序只有 4 个源,包括 ChainedConfigSource,我已经设置好了。但是添加了 2 个额外的源,它们是 appsettings.json 和我在加载特定环境 appsettings.environment.json.

之前声明的环境变量的副本

现在,当注入 class 时,最后添加的 appsettings.json 设置会通过 appsettings.environment.json

返回

阅读 Hostbuilder.cs class 的源代码,您将看到在 AddHostingConfiguration 中添加的配置被添加到 ApplicationConfiguration。

让我告诉你,你可以在https://github.com/aspnet/AspNetCore/blob/1c3fa82908fe2cb773626b6613843213286a482b/src/Microsoft.Extensions.Hosting/HostBuilder.cs

找到来源

构建调用将首先创建 HostingConfiguration,然后是 AppConfiguration。

这是构建 HostingConfiguration

的代码
    private void BuildHostConfiguration()
    {
        var configBuilder = new ConfigurationBuilder();
        foreach (var buildAction in _configureHostConfigActions)
        {
            buildAction(configBuilder);
        }
        _hostConfiguration = configBuilder.Build();
     }

现在,在 BuildAppConfiguration 中,您将看到 HostingConfiguration 添加到 AppConfiguration 之上

    private void BuildAppConfiguration()
    {
        var configBuilder = new ConfigurationBuilder();
        //Here _hostConfiguration gets added ontop
        configBuilder.AddConfiguration(_hostConfiguration);
        foreach (var buildAction in _configureAppConfigActions)
        {
            buildAction(_hostBuilderContext, configBuilder);
        }
        _appConfiguration = configBuilder.Build();
        _hostBuilderContext.Configuration = _appConfiguration;
    }

现在构建函数是私有的,无法 reset/clear 来自构建器的源代码。

如果您不想实现自己的 HostBuilder 版本,我建议您不要将主机设置与 App 设置分开

因此,根据文档,WebHostBuilder 会为您加载 appSettings.json 和 appSettings.env.json 文件。但它并没有说明 HostBuilder 也这样做,我认为这是由于缺乏文档,我无法确定源代码的来源。

为了解决这个问题,我更改了配置文件的设置方式。以前我在 appSettings.json 文件和 appSettings.env.json 文件中都有连接字符串。所以我遇到了最后添加的配置文件替换基本配置文件中的值的问题。我现在已将基于环境的设置仅移动到每个环境的配置文件中,并且仅将对所有环境全局的设置保留在基本配置文件中。

似乎 .NET 框架配置转换设置的旧习惯很难改掉。我无法确定是否应将从多个提供程序声明的 IConfiguration 中的相同键更改为最后加载的提供程序,我认为一些文档涵盖了这一点并确认了这一点,但现在我找不到它。

But 2 additional sources are added which are duplicates of the appsettings.json and the environment variables

我在使用 HostBuilder 的 Azure WebJob 中遇到了类似的问题,并注意到这两个源已附加到配置源列表的末尾。这产生了不良结果:appsettings.json 的开发设置覆盖了 appsettings.Production.json.

的生产设置

这些额外的来源 appear to be added here 来自 ConfigureWebJobs

解决方法是重新排序 HostBuilder 调用链,以便对 ConfigureWebJobs 的调用在对 ConfigureAppConfiguration 的调用之前 .这两个额外的源仍然存在,但由于它们现在位于配置源列表的开头,而不是末尾,因此它们没有不良影响。

可以重新排序 builder.Sources 以满足您的需要。例如,这里有一个扩展方法,您可以使用它在最后一个文件之后添加一个新的 JSON 文件,而不是在最后:

public static class ConfigurationBuilderExtensions
{
  public static IConfigurationBuilder AddJsonFileAfterLastJsonFile(this IConfigurationBuilder builder, string path, bool optional, bool reloadOnChange)
  {
    var jsonFileSource = new JsonConfigurationSource
    {
      FileProvider = null,
      Path = path,
      Optional = optional,
      ReloadOnChange = reloadOnChange
    };
    jsonFileSource.ResolveFileProvider();
    var lastJsonFileSource = builder.Sources.LastOrDefault(s => s is JsonConfigurationSource);
    var indexOfLastJsonFileSource = builder.Sources.IndexOf(lastJsonFileSource);
    builder.Sources.Insert(indexOfLastJsonFileSource == -1
      ? builder.Sources.Count
      : indexOfLastJsonFileSource + 1, jsonFileSource);
    return builder;
  }
}

然后您可以像这样使用它:

.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.AddJsonFileAfterLastJsonFile(
      "appsettings.Custom.json",
      optional: true,
      reloadOnChange: false);
})

您可以根据需要调整它,并将其插入到您需要的任何地方。