blog post image
Andrew Lock avatar

Andrew Lock

~3 min read

How to use machine-specific configuration with ASP.NET Core

In this quick post I'll show how to easily setup machine-specific configuration in your ASP.NET Core applications. This allows you to use different settings depending on the name of the machine you are using.

The tl;dr; version is to add a json file to your project containing your computer's name, e.g. appsettings.MACHINENAME.json, and update your ConfigurationBuilder in Startup with the following line:

.AddJsonFile($"appsettings.{Environment.MachineName}.json", optional: true)

Background

Why would you want to do this? Well, it depends.

When working on an application with multiple people, you will often run into a situation where you need different configuration settings for each developer's machine. Typically, we find that file paths and sometimes connection strings need to customised per developer.

In ASP.NET 4.x we found this somewhat of an ordeal to manage. Typically, we would create a connection string for each developer's machine, and create appsettings of the form MACHINENAME_APPSETTINGNAME. For example,

<configuration>
  <connectionStrings>
    <add name="DAVES-MACBOOK" connectionString="Data Source=DAVES-MACBOOK;Initial Catalog=TestApp; Trusted_Connection=True;" />
    <add name="JON-PC" connectionString="Data Source=JON-PC;Initial Catalog=TestAppDb; Trusted_Connection=True;" />
  </connectionStrings>
  <appSettings>
    <add key="DAVES-MACBOOK_StoragePath" value="D:\" />
    <add key="JON-PC_StoragePath" value="C:\Dump" />
  </appSettings>
</configuration>

So in this case, for the two developer machines named DAVES-MACBOOK and JON-PC, we have a different connection string for each machine, as well as different values for each of the StoragePath application settings.

This requires a bunch of wrapper classes around accessing appsettings which, while a good idea generally, is a bit of an annoyance and ends up polluting web.config.

The new way in ASP.NET Core

With ASP.NET Core, the updated configuration system allows for a much cleaner replacement of settings depending on the environment.

For example, in the default configuration for a web application, you can have environment specific appsettings files such as appsettings.Production.json which will override the default values in the appropriate environment:

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
        .AddEnvironmentVariables();
    Configuration = builder.Build();
}

Similarly, environment variables and UserSecrets can be used to override the default values. It's likely that in the majority of cases, these are perfect for the situation described above - they apply only to the single machine, and can override the default values provided.

In larger teams and projects this approach will almost certainly be the correct one - each individual machine contains the the specific settings for just that machine, and the repo isn't polluted with 101 different versions of the same setting.

However, it may be desirable in some cases, particularly in smaller teams, to actually store these values in the repo. Environment variables can be overwritten, UserSecrets can be deleted etc etc. With the .NET Core configuration system this alternative approach simple to achieve with a single additional line:

.AddJsonFile($"appsettings.{Environment.MachineName}.json", optional: true)

This uses string interpolation to insert the current machine name in the file path. The Environment class contains a number of environment-specific static properties like ProcessorCount, NewLine and luckily for us, MachineName. Using this approach, we can add a configuration file for each user with their machine-specific values e.g.

appsettings.DAVES-MACBOOK.json:

{
  "ConnectionStrings": {
    "DefaultConnection": "Data Source=DAVES-MACBOOK;Initial Catalog=TestApp; Trusted_Connection=True;"
  },
  "StoragePath": "D:\"
}

appsettings.JON-PC.json:

{
  "ConnectionStrings": {
    "DefaultConnection": "Data Source=JON-PC;Initial Catalog=TestAppDb; Trusted_Connection=True;"
  },
  "StoragePath": "C:\Dump"
}

Finally, if you want to deploy your machine-specific json files (you quite feasibly may not want to), then be sure to update the publishOptions section of your project.json:

{
  "publishOptions": {
    "include": [
      "wwwroot",
      "Views",
      "appsettings.json",
      "appsettings.*.json",
      "web.config"
    ]
  }
}

Note that you can use a wildcard in the appsettings name to publish all of your machine sepecific appsettings files, but be aware this will also publish all files of the format appsettings.Development.json etc too.

So there you have it, no more wrappers around the built in app configuration, per-machine settings stored in the application repo, and a nice clean interface, all courtesy of the cleanly designed .NET Core configuration system!

Andrew Lock | .Net Escapades
Want an email when
there's new posts?