Handling ASPNETCORE_ENVIRONMENT Environment Variable in IIS

.NET Core has built-in functionality that allows you to set up an environment variable called ASPNETCORE_ENVIRONMENT that tells the application which appsettings.json to use. I’ve tried to use this functionality on VMs in Azure with no luck. My applications seem to ignore this variable setting on VMs. It did work for me when deployed as an app service.

If you host your website on a shared server, you may not have any rights to create system environment variables.

This tutorial is using Visual Studio 2022.

When a .NET Core application first runs, in theory, it looks for the ASPNETCORE_ENVIRONMENT environment variable and uses that to select the proper appsettings.json to use to run the application. By default, a new application in Visual Studio will create three files:

  • appsettings.json
  • appsettings.development.json
  • appsettings.production.json

if the application doesn’t find the environment variable, it defaults to appsettings.production.json

Here’s the kicker, if the application doesn’t find the environment variable, it defaults to appsettings.production.json. This functionality is entirely unacceptable to me. If you deploy your app to a new server, would you want it to default to production values? I don’t.

Fortunately, there is a way to control all this behavior right from within your application code using web.config transformations. Since .NET Core doesn’t really depend on web.config files, many developers with only a few years experience may not even know about web.config transformations.

web.config Transformations

The web.config file is a file that is read by Internet Information Services (IIS) that is merged with the local maching.config file and tells IIS how to handle certain things. Often, if you make configuration changes in IIS, all it really does is update the web.config file for that application.

There is an XML schema definition called “XML-Document-Transform” that is prefixed with “xdt” which allows you to have different versions of your web.config file which can actually update values in the base web.config file when you deploy an application. Since most of us don’t use this file any longer, we usually don’t look at it, nor do we normally set up transformations. We’re going to use this functionality to control which appsettings.json our application uses based on which configuration we use to deploy.

Visual Studio Configuration Manager

At the top of the Visual Studio IDE, there is a drop-down for configuration. Typically, it will say “Debug”. If you click the drop-down arrow, you can select “Configuration Manager…”, or optionally, you can right-click on the project name and select the same entry.

The default configurations can be viewed in the “Active solution configuration:” drop-down. Usually it’s just “Debug” and “Release”.

  1. Click the drop down and select “<New…>”.
  2. Let’s name it “UAT”
  3. Copy settings from: “Debug”
  4. Create new project configurations should be checked
  5. Click on “OK”
  6. Click on “Close”

You’ll notice that your drop-down at the top of Visual Studio now says “UAT”.

appsettings.config files

Later versions of the .NET Core, post version 3.1 don’t seem to create the appsettings.Production.json file by default. However, if you have an older project that has been upgraded, the file may still exist. I’ll be using a project from a post on Lookups to demonstrate this technique.

In your main web application:

  1. Right-click on your appsettings.json file and select “Copy”
  2. Right-click on your project name and select “Paste”
  3. Rename the file “appsettings – Copy.json” to “appsettings.UAT.json”

Your appsettings entries should now look like:

You can edit the appsettings.UAT.json file and modify any of the entries to match what you need for your UAT environment/server.

I highly recommend that you delete the appsettings.Production.json. I typically use an appsettings.PROD.json etc. This will prevent the application from accidentally defaulting to the production config when deploy to a new environment/server.

Creating the web.config transformation

Now let’s look at your current web.config file. There is a chance that your project doesn’t have one. Here is what my default one looks like, you can copy this into a new one you create, but make sure to update the arguments in the “aspNetCore” key.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
	<location path="." inheritInChildApplications="false">
		<system.webServer>
			<aspNetCore processPath="dotnet" arguments=".\YTG.MVC.Lookups.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess">
				<environmentVariables>
					<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Development" />
				</environmentVariables>
			</aspNetCore>
		</system.webServer>
	</location>
</configuration>

Once you have the file, it’s important that you have the entry:

<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Development" />

This tells the runtime that when you run the application, it will use the “Development” configuration, which will default to picking up values in your appsettings.Development.json. This will work even though we didn’t create a configuration called Development, we just still have “Debug” for local running.

Visual Studio used to have the option to right-click your web.config file and select “Add Transformations”, but I don’t see it any longer in the latest version of Visual Studio 2022. So we’ll create the transform manually.

  1. Right-click on the web.config and select “Copy”
  2. Right-click on your project name and select “Paste”
  3. Rename the “web – Copy.config” file to “web.UAT.config”

Double click the web.UAT.config file and modify the second line “configuration” to look like this:

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">

This lets us use the xdt namespace.

Then modify the environmentVariable line to look like this:

<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="UAT" xdt:Locator="Match(name)" xdt:Transform="Replace" />

This tells the build process to replace the value with the same name from the web.config with the value from this file.

Now, when you publish this project, you can select the “UAT” configuration and it will push a web.config with your project that automatically tells your application to use the values in the appsettings.UAT.json file. If you publish from the command line or through Jenkins, that command would looks like this:

dotnet publish –configuration UAT

The web.config in your publish location should have the line:

<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="UAT" />

So now you no longer have to depend on that system environment variable existing on the server.

You can read more about this on Microsoft’s site:

https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/transform-webconfig?view=aspnetcore-7.0