Environments In ASP.NET Core

In ASP.NET core there is this concept of “environments” where you set at the machine level (Or sometimes at the code level) what “environment” you are in. Environments may include development, staging, production or actually any name you want. While you have access to this name via code, the main uses are actually to do configuration swaps at runtime. In full framework you might have previously used web.config transforms to transform the configuration at build time, ASP.NET core instead determines it’s configuration at runtime.

It should be noted that there are two uses of the word “environment variables” being used here. The first is that “Environment Variables” are used to describe the actual definition of an environment variable on your machine. The second is that you can add an “environment” to that environment variables list to describe what ASP.NET Core environment you are using… That may sound confusing but it will all come together at the end!

Setting Environment Variable In Visual Studio

When developing using Visual Studio, any debugging is done inside an IIS Express instance. You can set Environment variables for debugging by right clicking your project, selecting properties, and then selecting “Debug” on the left hand menu. By default you should see that a variable has been added for you called “ASPNETCORE_ENVIRONMENT” and it’s value should be Development.

You can set this to another value (like “Staging”), when you want to debug using another configuration set. It should be noted that editing this value actually edits your “launchSettings.json” and sets the variable in there. It ends up looking like this :

"IIS Express": {
  "commandName": "IISExpress",
  "launchBrowser": true,
  "environmentVariables": {
	"ASPNETCORE_ENVIRONMENT": "Development"
  }
}

Setting Environment Variable Machine Wide

You will need to set the ASP.NET core environment machine wide if…

  • You are not using Visual Studio/IIS Express
  • You are running the website locally but using full IIS
  • You are running the website on a remote machine for staging/production

To set your entire machine to an environment you should do the following :

For Windows in a Powershell window

$Env:ASPNETCORE_ENVIRONMENT = "Development"
Get-ChildItem Env:

For Mac/Linux edit your .bashrc or .bash_profile file and add

export ASPNETCORE_ENVIRONMENT=Development

It should be noted that setting this up machine wide means that your entire machine (And every project within it) is going to run using that environment variable. This is extremely important if you are currently running multiple websites on a single box for QA/Staging purposes and these each have their own configurations. Setting the environment machine wide may cause issues because each site will think they are in the same environment, if this is you, read the next section!

Setting Environment Variable via Code

You can go through mountains of official ASP.NET core documentation and miss the fact that you can set the ASP.NET Core Environment through code. For some reason it’s a little known feature that makes the use case of multiple websites with different environments live on the same machine.

In your ASP.NET core site, you should have a program.cs. Opening this you will see that you have a WebHostBuilder object that gets built up. You can actually add a little known command called “UseEnvironment” like so :

public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args)
		.ConfigureWebHostDefaults(webBuilder =>
		{
			webBuilder.UseEnvironment("Production");
			webBuilder.UseStartup();
		});

Obviously as a constant string it’s probably not that helpful, but this is regular old C# code so how you find that string is up to you. You could load a text file for example and from there decide which environment to use. Any logic is possible!

Note for projects below .NET Core 3, the UseEnvironment call does exist, but the way you build the hostbuilder is slightly different so you may need to play around a bit. But in general it would look something like :

public static void Main(string[] args)
{
	var host = new WebHostBuilder()
		.UseKestrel()
		.UseEnvironment("Development")
		.UseContentRoot(Directory.GetCurrentDirectory())
		.UseIISIntegration()
		.UseStartup()
		.Build();

	host.Run();
}

Accessing Environment via Code

To access the environment in your code (Such as a controller), you just have to inject IHostingEnvironment into your controller. The interface is already setup by calling “AddMvc” in your ConfigureServices method so you don’t need to add the interface to your service collection manually.

Here is some example code that returns the environment I am currently in :

public class HomeController : Controller
{
	private readonly IHostingEnvironment _hostingEnvironment;

	public HomeController(IHostingEnvironment hostingEnvironment)
	{
		_hostingEnvironment = hostingEnvironment;
	}

	[HttpGet]
	public IActionResult Get()
	{
		return Ok(_hostingEnvironment.EnvironmentName);
	}
}

Swapping Config Based Off Environment

In your startup.cs there is a method called “Startup” that builds your configuration. By default it adds a json file called “appsettings.json” but it can be used to add a file called “appsettings.{environment}.json where environment is swapped out for the environment you are currently running in. The code looks like this :

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

	Configuration = builder.Build();
}

Any settings in your base appsettings.json are overwritten using your environment specific file.

Configuration itself is a massive topic and Microsoft has already done an incredible job of it’s documentation so head over and read it here.

Naming Conventions Per Environment

Again, another little known “feature” of using environments is that naming conventions can be used to completely change how your application starts. By default, you should have a file called startup.cs that contains how your app is configured, how services are built etc. But you can actually create a file/class called “startup{environmentname}.cs” and it will be run instead of your default if it matches the environment name your app is currently running in.

Alternatively, if you stick with a single startup.cs file, the methods Configure and ConfigureServices can be changed to Configure{EnvironmentName} and ConfigureServices{EnvironmentName} to write completely different pipelines or services. It’s not going to be that handy on larger projects because it doesn’t call both the default and the environment specific methods, it only calls one which could lead to a lot of copy and pasting. But it’s handy to know!

4 thoughts on “Environments In ASP.NET Core”

  1. Thanks a lot for writing this articles. It was most helpfull to figure out how to make my services take the right configuration when they’re both(DEV and QA) living on the same server.

    Reply
  2. Thanks, but still missing the config transformation from ASP.NET.
    If nuget library reads from appsetting.json – env config does NOT work.

    Reply
    • A nuget library should not be reading from appsetting.json. It would *always* allow you to pass in configuration. What if you wanted to use Azure Keyvault? Or another secret store? A nuget package should never dictate how your configuration is stored.

      Reply

Leave a Comment