.Net Core配置应用程序配置添加额外来源覆盖特定环境设置。

15

在使用IConfigurationBuilder配置.NET Core 2.1应用程序的通用主机时,我配置了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。但是会添加两个额外的来源,它们是在加载特定于环境的appsettings.environment.json之前我声明的appsettings.json和环境变量的重复项。

现在当注入到类中时,返回的是最后添加的appsettings.json设置而不是appsettings.environment.json的设置。

5个回答

12

您可以重新排序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);
})

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

你应该将它上传到 Github 和 NuGet。这对于保留环境变量和命令行选项作为最后添加的选项非常有用。 - BozoJoe

11
但是,又添加了两个来源,这两个来源是appsettings.json和环境变量的副本。
我在使用HostBuilder的Azure WebJob中遇到了类似的问题,并注意到这两个源被追加到配置源列表的末尾。这会产生不良结果:来自appsettings.json的开发设置覆盖了来自appsettings.Production.json的生产设置。
这些额外的来源通过ConfigureWebJobs在此处添加
解决方法是重新排列HostBuilder调用链,使调用ConfigureWebJobs的操作出现在调用ConfigureAppConfiguration之前。这两个额外的源仍然存在,但由于它们现在位于配置源列表的开头而不是末尾,因此不会产生不良影响。

4
这让我抓狂了三个小时。谢谢。现在需要找出为什么.bind<T>()默认使用appsettings.json而不是appsettings.{environment}.json文件。 - Hardrada

6

2023 更新

查看 .net 7 应用程序示例。

首先清除所有配置源,然后根据您的需求设置它们。

// Program.cs

var builder = WebApplication.CreateBuilder(args);

// Clear Config sources
builder.Configuration.Sources.Clear();

// Add config sources from lowest priority to highest
builder.Configuration.AddJsonFile("mysettings.json");
builder.Configuration.AddEnvironmentVariables();

// Build and run app
var app = builder.Build();
app.MapGet("/", () => "Hello");
app.Run();

4
根据文档,WebHostBuilder会为您加载appSettings.json和appSettings.env.json文件。但是它并没有提到HostBuilder也会这样做,我认为这是由于缺乏文档说明,我无法确定源代码中来自哪里。
为了解决这个问题,我改变了我的配置文件设置方式。以前,连接字符串既在appSettings.json文件中,也在appSettings.env.json文件中。所以我遇到了一个问题,即最后添加的配置文件替换了基本配置文件中的值。现在,我只将基于环境的设置放入每个环境的配置文件中,并且只保留适用于所有环境的设置在基本配置文件中。
似乎.NET框架配置转换设置的老习惯难以改掉。我无法确定从多个提供程序声明的IConfiguration中相同的键是否应更改为最后加载的提供程序,我认为有些文档涵盖了这一点并予以确认,但现在我找不到了。

4
阅读Hostbuilder.cs类的源代码,您会发现在AddHostingConfiguration中添加的配置将被添加到ApplicationConfiguration中。
让我给您展示一下,您可以在此处找到源代码:https://github.com/aspnet/AspNetCore/blob/1c3fa82908fe2cb773626b6613843213286a482b/src/Microsoft.Extensions.Hosting/HostBuilder.cs build调用将首先创建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;
    }

现在 Build 函数是私有的,没有办法从构建器中重置/清除源。如果您不想实现自己的 HostBuilder 版本,我建议不要将主机设置与您的 Appsettings 分开。

我正在考虑这个问题;我验证了构建配置中的源代码只引用了appsettings.json,没有指向hostsettings.json。在你的建议下,我尝试注释掉以下行: configurationBuilder.AddJsonFile("hostsettings.json", optional: true); 但是仍然有相同数量的提供程序,其中2个指向appsettings.json文件。 - Ryan Holsman
阅读您提交的源文件后,我发现创建了一个新的ConfigurationBuilder,然后添加了主机配置。然后按顺序调用了您设置的每个操作。这是否意味着最近的AppConfiguration会覆盖HostConfiguration? - Ryan Holsman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接