Create and deploy different configurations for different environments in .NET Core

I recently had an issue when I tried to deploy the correct configuration for a .NET Core application. I managed to mix up the environment names used in the application itself, in IIS and in Octopus Deploy. The result was that none of my configuration files worked as expected, with errors everywhere.

In this blog post I will try to explain how the environment names are defined and how to set up the specific configuration for each environment.

Solution architecture:

  • Application: .NET Core web application
    • Configuration: appsettings.json
  • Hosting: Windows server with IIS
    • Configuration: web.config
  • Deployment: Octopus Deploy
    • Configuration: Settings page in Octopus Deploy

Environment names in Octopus Deploy

The names used for each environment in Octopus Deploy are only there to help the tech team differentiate between the different servers and their purpose. The application and the server don't use (or know) Octopus Deploy's environment names.

In our setup, the environment names in Octopus Deploy are as follows:

  • Test
  • Preprod
  • Prod

Configure IIS: web.config

Each web application in IIS has its own configuration, web.config. When we are developing an application that will be deployed to many different servers, we use transformation files to set up the configuration for each environment.

Octopus Deploy merges the default web.config file with the transformation file for the environment it is deploying to, and creates a unique web.config file for that server.

In our project we have the following config files, with transformations for each environment in Octopus Deploy:

  • web.config
  • web.Test.config
  • web.Preprod.config
  • web.Prod.config

When we deploy to one of the servers in the Preprod environment, Octopus Deploy opens web.config, adds the transformations in web.Preprod.config and uploads the changed web.config file to the server.

The file web.Preprod.config is not used anymore after that, and doesn't have to be uploaded to the server.

Configure the .NET Core application: appsettings.json

.NET Core applications are configured with JSON files. The standard file names are appsettings.json for the default configuration and appsettings.EnvironmentName.json for the environment specific configuration.

Instead of transforming on deploy, the application reads from both the default configuration and the environment specific configuration on the fly. This means that both appsettings.json and appsettings.Environment.json need to be uploaded to the server.

Now, remember that the application does not know the environment names defined in Octopus Deploy. The easiest way to tell the application which environment it is running in, is to define it in web.config with the variable environmentVariable. Here is an excerpt from the transformation file web.Prod.config:

<environmentVariables>
    <environmentVariable 
        name="ASPNETCORE_ENVIRONMENT" 
        value="Production" 
        xdt:Transform="SetAttributes" 
        xdt:Locator="Match(name)" />
</environmentVariables>

Here the environment name is set to "Production".

Standard environment names in .NET Core

.NET Core has these standard environment names:

  • Development
  • Test
  • Staging
  • Production

You are free to use any name you would like for the each environment, but by following the conventions, you get some nice methods, like isDevelopment() to have the application behave differently in different environments.

In our project, we considered using the same environment names that we already had in Octopus Deploy, but ended up with using default names in .NET Core.

Summary

In our project, we need the following configuration and transformation files to configure IIS. The environment names are defined in Octopus Deploy:

  • web.config
    • web.Test.config
    • web.Preprod.config
    • web.Prod.config

We also need these appsettings files to configure the application. The environment names are defined in web.config:

  • appsettings.json
    • appsettings.Development.json
    • appsettings.Test.json
    • appsettings.Staging.json
    • appsettings.Production.json