TekOnline

Why ASPNETCORE_ENVIRONMENT vs DOTNET_ENVIRONMENT Causes So Much Frustration (And How To Fix It)

If you’ve ever set:

ASPNETCORE_ENVIRONMENT=Production

…only to find your app still thinks it’s running in Development — welcome to the club.

This has caused years of confusion in the .NET ecosystem, especially since .NET Core evolved into the “generic host” world.

Let’s break it down properly.


The Symptom

You write something like:

var runtimeEnvironment = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT");var isProductionEnvironment = string.Equals(
runtimeEnvironment,
"Production",
StringComparison.OrdinalIgnoreCase
);

You set:

"ASPNETCORE_ENVIRONMENT": "Production"

And…

isProductionEnvironment == false

🤯


The Root Cause

There are two environment variables in play:

VariableUsed ByTypical App Type
ASPNETCORE_ENVIRONMENTWeb HostASP.NET Core Web Apps
DOTNET_ENVIRONMENTGeneric HostWorker services, Console apps, modern .NET hosting

The problem?

.NET Core evolved.

Early ASP.NET Core used ASPNETCORE_ENVIRONMENT.

Later, when Microsoft introduced the Generic Host (Host.CreateDefaultBuilder()), they introduced DOTNET_ENVIRONMENT.

Now we live in a world where:

  • Some parts of the runtime check ASPNETCORE_ENVIRONMENT
  • Some check DOTNET_ENVIRONMENT
  • Some prioritise one over the other
  • And your own code might be reading the wrong one entirely

Why This Is So Frustrating

  1. Both variables can exist at the same time.
  2. One can override the other.
  3. VS Code tasks.json and launch.json handle env vars differently.
  4. dotnet watch can behave differently than dotnet run.
  5. IIS ignores both and uses its own configuration.
  6. Azure App Service sets its own environment values.

It’s the perfect storm of “it works on my machine.”


What Actually Happens Under The Hood

If you’re using:

var builder = WebApplication.CreateBuilder(args);

The environment name ultimately comes from:

IHostEnvironment.EnvironmentName

That value is populated by:

  1. DOTNET_ENVIRONMENT
  2. Fallback to ASPNETCORE_ENVIRONMENT
  3. Default = "Production"

So if your code manually reads:

Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT")

…then setting only ASPNETCORE_ENVIRONMENT will do absolutely nothing.


The Clean Way To Do It

Instead of manually reading environment variables:

❌ Don’t do this:

var env = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT");

✅ Do this:

var isProduction = app.Environment.IsProduction();

Or:

var envName = app.Environment.EnvironmentName;

This removes all ambiguity.


The Practical Fix (When You’re Sick of It Not Working)

In VS Code tasks.json, just set both:

"env": {
"ASPNETCORE_ENVIRONMENT": "Production",
"DOTNET_ENVIRONMENT": "Production"
}

Problem solved.


Why Microsoft Didn’t Just Pick One

Historical evolution.

  • ASP.NET Core 1.x → ASPNETCORE_ENVIRONMENT
  • .NET Core Generic Host → DOTNET_ENVIRONMENT
  • Backward compatibility had to be preserved
  • So now both exist

It’s not a bug.
It’s legacy design inertia.


Real Production Advice

If you’re deploying properly:

  • IIS sets environment in web.config
  • Azure sets environment in Application Settings
  • Docker sets environment in container config
  • Windows Services use system environment variables

The confusion mainly happens in:

  • Local dev
  • VS Code
  • dotnet watch
  • Manual CLI runs

The Mental Model That Prevents Future Pain

Think of it this way:

ASPNETCORE_ENVIRONMENT is the old web host world
DOTNET_ENVIRONMENT is the generic host world

Modern apps use the generic host.

So if in doubt — set both.


Final Takeaway

If your Production check is false and you’re sure it shouldn’t be:

  1. Print both environment variables.
  2. Check app.Environment.EnvironmentName.
  3. Stop manually reading env vars.
  4. Use the framework helpers.

And if you’re debugging in VS Code?

Check launch.json before you lose your sanity.


Posted

in

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *