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

Posted

技术标签:

【中文标题】.Net Core ConfigureAppConfiguration 添加额外的源覆盖环境特定设置【英文标题】:.Net Core ConfigureAppConfiguration adding additional sources overriding environment specific settings 【发布时间】:2019-05-21 05:24:55 【问题描述】:

在带有通用主机的 .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 之前声明的环境变量的副本。

现在,当将 appsettings.json 注入到一个类中时,最后添加的 appsettings.json 设置将通过 appsettings.environment.json 返回

【问题讨论】:

【参考方案1】:

但是添加了 2 个额外的源,它们是 appsettings.json 和环境变量的副本

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

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

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

【讨论】:

这让我抓狂了 3 个小时。谢谢。现在找出为什么 .bind() 默认为 appsettings.json 而不是 appsettings.environment.json 文件..【参考方案2】:

阅读 Hostbuilder.cs 类的源代码,您会看到 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;
    

现在构建功能是私有的,无法从构建器重置/清除源。

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

【讨论】:

我正在考虑这个;我验证了构建配置中的源仅引用了 appsettings.json,并且没有一个指向 hostsettings.json。根据您的建议,我尝试注释掉行 configurationBuilder.AddJsonFile("hostsettings.json", optional: true);并且仍然有相同数量的提供程序,其中 2 个指向 appsettings.json 文件。 阅读您提交的源文件后,我看到创建了新的 ConfigurationBuilder,然后添加了主机配置。然后按顺序调用您设置的每个操作。这是否意味着最新的 AppConfiguration 会覆盖 HostConfiguration?【参考方案3】:

可以重新订购builder.Sources 以满足您的需求。例如,这是一种扩展方法,您可以使用它在最后一个 JSON 文件之后添加新的 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);
)

您可以根据自己的需要对其进行调整,并将其插入到您需要的任何位置。

【讨论】:

【参考方案4】:

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

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

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

【讨论】:

以上是关于.Net Core ConfigureAppConfiguration 添加额外的源覆盖环境特定设置的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core (.NET Core) and ASP.NET Core (.NET Framework)区别

net/core/pktgen.c怎么修改

细说.net core Startup

Asp.net core 配置文件

asp.net core 注入后仍然报错?

Asp.Net core (Full .Net framework) vs Asp.Net core (.Net Core) 性能