Config transformations in ASP.NET Core

This is part 2 in our series about ASP.NET Core:

Most parts of elmah.io consist of small services. While they may not be microservices, they are in fact small and each do one thing. We recently started experimenting with ASP.NET Core for some internal services and are planning a number of blog posts about the experiences we have made while developing these services. This is the second part in the series about the configuration system available in Core.

Config transformations in ASP.NET Core

You probably know web.config transformations available in ASP.NET. Using a transform XML file, you can replace, insert, remove settings from any XML file. Transformations is primarily used to have sets of variables for different environments like localhost, staging and production. Since Core no longer use web.config for application settings, web.config transformations no longer apply. Luckily, Core introduces a similar concept for its JSON configuration files. JSON is a great format for configuration since it is well supported by Visual Studio and Code and there a log of online tools available like this JSON Validator and Formatter.

Let's extend the example from the previous post. To define another set of variables for the production environment, create a new JSON file named appsettings.Production.json. Notice how the new file is automatically nested beneath appsettings.json (previously this would require an extension for VS):

appsettings.json file nesting

The nice thing about transformations in Core is, that you are no longer required to write cryptic xdt attributes. By specifying sections and variables with the same names as appsettings.json, Core automatically replaces the values.

To override the value of the Hello setting, add the following to appsettings.Production.json:

{
  "AppSettings": {
    "Hello": "from production"
  }
}

Would your users appreciate fewer errors?

➡️ Reduce errors by 90% with elmah.io error logging and uptime monitoring ⬅️

Verify that appsettings.{env.EnvironmentName}.json is registered in Startup.cs:

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();

This tell Core to first load appsettings.json and then a settings file of the same name, but with the current environment as part of the file name. So how does Core resolve env.EnvironmentName? Simply by looking at an environment variable named ASPNETCORE_ENVIRONMENT.

ASPNETCORE_ENVIRONMENT were called ASPNET_ENV up until the rename of Core. You will still find blog posts referring to the old name.

If no environment variable with that name is found, Core automatically uses the value Production. Let's start the project to see the value used in the web app:

ASP.NET Core website with config variable

Wait a minute. We just added the appsettings.Production.json file and I told you that a value of Production is used if no environment variable named ASPNETCORE_ENVIRONMENT is specified. Why don't we see the value of from production then? Say hello to launchSettings.json. The launchSettings.json file (located in the Properties folder) contains a list of different profiles used to tell Visual Studio how to host and run your website. I won't go into more details about launchSettings.json in this post but in short, the profiles end up in this dropdown:

ASP.NET Core profiles

By right clicking the project and selecting Properties or by simply opening launchSettings.json, you will see the list of profiles:

{
  ...
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
         "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "WebApplication14": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

Both profiles define an environment variable named ASPNETCORE_ENVIRONMENT with the value of Development. Since we don't have a file named appsettings.Development.json, the default values in appsettings.json is used.

To test the production variables, replace the value of ASPNETCORE_ENVIRONMENT with Production and restart the browser:

ASP.NET Core using appsettings.Production.json

To test your transformation file without changing variables inside Visual Studio, you can use this Appsettings.json Transformation Tester.

Change back to Development, since we don't want to use production variables on the development environment. In the next post, we'll discuss how to deploy ASP.NET Core with transformations to Azure.

elmah.io: Error logging and Uptime Monitoring for your web apps

This blog post is brought to you by elmah.io. elmah.io is error logging, uptime monitoring, deployment tracking, and service heartbeats for your .NET and JavaScript applications. Stop relying on your users to notify you when something is wrong or dig through hundreds of megabytes of log files spread across servers. With elmah.io, we store all of your log messages, notify you through popular channels like email, Slack, and Microsoft Teams, and help you fix errors fast.

See how we can help you monitor your website for crashes Monitor your website