Environment Specific Error Pages In ASP.NET Core

I wanted the detailed exception page (stack trace and all) in UAT, but never in production. I had been using a custom ResolvDebug setting for this, which turned out to be on by default in appsettings.json, so prod was quietly showing stack traces. This is the standard way to do it instead, with ASPNETCORE_ENVIRONMENT.

1. Switch on the environment in Program.cs

1
2
3
4
5
6
7
8
9
10
11
if (app.Environment.IsDevelopment() || app.Environment.IsEnvironment("Uat"))
{
// Stack traces, never in Production
app.UseDeveloperExceptionPage();
}
else
{
// Generic page, no details
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}

IsDevelopment() and IsProduction() are built in, any other name goes through IsEnvironment("<name>"). If ASPNETCORE_ENVIRONMENT is not set at all, the default is Production, which is the safe way round.

Docs: Use multiple environments

2. Set it per deployment

In my UAT GitHub Actions workflow it is one more environment variable on the container app deploy:

1
2
environmentVariables: |
Database__ResolvDb__ConnectionString=$DB_CONN ASPNETCORE_ENVIRONMENT=Uat

Prod sets ASPNETCORE_ENVIRONMENT=Production and locally launchSettings.json sets Development. The name can be anything, Uat and Staging both work, just match it in IsEnvironment(...).

As a bonus, appsettings.Uat.json now layers over appsettings.json for UAT only if you ever need UAT specific settings.

3. Add a route that throws

You need a way to prove it, so I have an action that always blows up:

1
2
3
4
5
// Test endpoint to force an exception and check the error page
public IActionResult TestError()
{
throw new InvalidOperationException("Test exception to verify error handling");
}

Hit /Home/TestError in each environment:

  • UAT: the detailed exception page with the stack trace.
  • Prod: only the generic error page, no stack trace.

Mine sits behind the sign-in the app requires by default, so I have to be logged in to hit it. Consider locking it to an admin policy or removing it once you have checked prod.

Docs: Handle errors in ASP.NET Core

Things to know

  • Setting a custom environment name means IsDevelopment() is false there, so check anything else that treats “not Development” as production.
  • Deciding the environment from the request host (I had an EnvironmentResolver doing this) is fragile, a new domain and it silently says “dev”. Use the environment variable instead.