My software development journey

Configuration in .NET Core part 2/3

September 13, 2021

Let’s continue our journey by adding a JSON file as a source of configuration. If your instinctive reaction is, well that should be easy, I only need to add the NuGet package and configure it, you are right! Well, almost. 🙂 Let’s first add a JSON file named appsettings.json and mark it to be copied to the output. The file contains the following values:

{
  "MySetting": "Setting from JSON file",
  "Subsection": {
    "MyIntValue": 5,
    "IntArray": [10, 11]
  }
}

We also add Microsoft.Extensions.Configuration.Json nuget package and the required configuration:

var configBuilder = new ConfigurationBuilder()
  .SetBasePath(Directory.GetCurrentDirectory())
  .AddJsonFile("appsettings.json", optional: true,
    reloadOnChange: true);

Aside from adding the JSON file configuration, we also need to set the base directory path, from where the files will be read. For JSON file settings we configure the name of our file and as the method call suggests mark it optional and force a reload of configuration when it changes. Note that as soon as you bind your settings object, it is filled with current values in configuration, so changes in your settings file will not be reflected there. If you require updates, take a look at the appropriate IOptions interface.

How about adding nested settings file, like you can see in ASP.NET Core project? You know, where based on environment the appropriate file is selected? Well let’s try to recreate that:

var environmentConfigBuilder = new ConfigurationBuilder()
    .AddEnvironmentVariables("DOTNET_");
var environmentConfigRoot = environmentConfigBuilder.Build();
using var environmentConfigDispose =
  environmentConfigRoot as IDisposable;
var environmentName =
  environmentConfigRoot[HostDefaults.EnvironmentKey];

var configBuilder = new ConfigurationBuilder()
    .SetBasePath(Directory.GetCurrentDirectory())
    .AddJsonFile("appsettings.json", optional: true,
      reloadOnChange: true)
    .AddJsonFile($"appsettings.{environmentName}.json",
      optional: true, reloadOnChange: true);

As a first step, we need to read out the environment variable that gives us the name of the environment, so we can in the second step select the required file. I chose here to use HostDefaults.EnvironmentKey found in Microsoft.Extensions.Hosting.Abstractions to keep implementation consistent with the default WebHost setup. Here you could define and use your key. To see this in action let’s update our launchsetttings.json:

"environmentVariables": {
  "DOTNET_ENVIRONMENT": "Development",
  "DOTNET_Subsection:MyIntValue": "1"
}

And add an appsettings.Development.json file, again marking it to be copied to output:

{
  "MySetting": "Setting from DEVELOPMENT JSON file"
}

This results in “MySetting” from the development file overriding the setting from the appsettings.json file:

Using my setting: Setting from DEVELOPMENT JSON file
Using my subsection setting: parsed value 5

As a final step, let’s display the appsettings.Development.json as depending on appsettings.json in Visual Studio. To do that, modify your project file as follows:

<ItemGroup>
  <None Update="appsettings.Development.json">
    <DependentUpon>appsettings.json</DependentUpon>
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </None>
  <None Update="appsettings.json">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </None>
</ItemGroup>

The important part is the DependentUpon tag. Now your settings should be displayed like this in Visual Studio:

appsettings with dependency

Sources: