When using the IConfigurationBuilder in a .NET Core 2.1 application with a Generic Host I configure 4 sources; but after the scope of ConfigureAppConfiguration there are 6 sources.
At some point 2 additional source I have already loaded are added a second time in an order that is causing appsettings.Environment.json values to be hidden. I have also tried removing the hostsettings.json configuration and verified that is not affecting this. This is for an Azure Webjob using WebjobsSDK 3.0 and .Net Core 2.1
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);
})
I expect a configuration provider with only the 4 sources, including the ChainedConfigSource, I have setup to be included. But 2 additional sources are added which are duplicates of the appsettings.json and the environment variables which I declared before loading the environment specific appsettings.environment.json.
Now when injected the into a class the appsettings.json settings were added last are returned over a appsettings.environment.json
You could add the IConfiguration instance to the service collection as a singleton object in ConfigureServices : public void ConfigureServices(IServiceCollection service) { services. AddSingleton<IConfiguration>(Configuration); //... }
CreateDefaultBuilder()Initializes a new instance of the WebHostBuilder class with pre-configured defaults.
But 2 additional sources are added which are duplicates of the
appsettings.json
and the environment variables
I had a similar issue with an Azure WebJob using the HostBuilder
, and noticed that these 2 source were appended to the end of the list of config sources. This had undesirable results: development settings from appsettings.json
overwrote the production settings fromappsettings.Production.json
.
These additional sources appear to be added here by by ConfigureWebJobs
.
The fix was to re-order the HostBuilder
call chain so that the call to ConfigureWebJobs
comes before the call to ConfigureAppConfiguration
. These extra two sources are still present, but since they are now at the start of the list of configuration sources, and not at the end, they have no undesirable effects.
Reading the source code for the Hostbuilder.cs class you will see that the Configuration added in the AddHostingConfiguration gets added to the ApplicationConfiguration.
Let me show you, you can find the source at https://github.com/aspnet/AspNetCore/blob/1c3fa82908fe2cb773626b6613843213286a482b/src/Microsoft.Extensions.Hosting/HostBuilder.cs
The build call will first create the HostingConfiguration, then the AppConfiguration.
Here's the code that builds the HostingConfiguration
private void BuildHostConfiguration()
{
var configBuilder = new ConfigurationBuilder();
foreach (var buildAction in _configureHostConfigActions)
{
buildAction(configBuilder);
}
_hostConfiguration = configBuilder.Build();
}
Now in the BuildAppConfiguration you will see that the HostingConfiguration gets added ontop of the 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;
}
Now the Build functions are private and there is no way to reset/clear sources from the builder.
If you dont want to implement your own version of the HostBuilder I'd suggest not seperating the Host settings from your Appsettings
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With