Environments
π― What You'll Learn
- Understanding ASP.NET Core environments
- The ASPNETCORE_ENVIRONMENT variable
- Built-in environments: Development, Staging, Production
- Environment-specific configuration and behavior
- Detecting environments in code
- launchSettings.json explained
- Setting environments in different hosting scenarios
- Best practices for InvenTrack deployment
What Are Environments?
Environments let you configure your application differently based on where it's running. You typically have different settings, logging levels, and behaviors for development vs production.
Development: Detailed logging, Swagger UI, local database
Staging: Production-like, but for testing before release
Production: Minimal logging, no debug tools, production database
The ASPNETCORE_ENVIRONMENT Variable
ASP.NET Core determines the current environment from the
ASPNETCORE_ENVIRONMENT environment variable.
Built-in Environment Names
| Environment | Purpose | Typical Use |
|---|---|---|
| Development | Local development | Your machine, detailed errors, Swagger |
| Staging | Pre-production testing | QA environment, production-like setup |
| Production | Live application | Customer-facing, optimized, secure |
You can create custom environments like "Testing", "UAT", or "Demo". The names are case-insensitive but conventionally use PascalCase.
Setting the Environment
Method 1: launchSettings.json (Development)
When running locally with dotnet run or Visual Studio, the environment is
set in Properties/launchSettings.json:
{
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
launchSettings.json is only used during local development. It's NOT deployed
to production. Don't rely on it for production configuration!
Method 2: Environment Variable (Production)
# Set for current session
$env:ASPNETCORE_ENVIRONMENT = "Production"
# Set permanently (system-wide)
[System.Environment]::SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Production", "Machine")
# Set for current session
export ASPNETCORE_ENVIRONMENT=Production
# Add to ~/.bashrc for persistence
echo 'export ASPNETCORE_ENVIRONMENT=Production' >> ~/.bashrc
Method 3: Command Line
# Windows
dotnet run --environment Production
# Linux/macOS
ASPNETCORE_ENVIRONMENT=Production dotnet run
Method 4: Azure App Service
In Azure Portal:
- Navigate to your App Service
- Go to Configuration β Application settings
- Add
ASPNETCORE_ENVIRONMENT=Production - Click Save
Method 5: Docker
FROM mcr.microsoft.com/dotnet/aspnet:8.0
ENV ASPNETCORE_ENVIRONMENT=Production
COPY . /app
WORKDIR /app
ENTRYPOINT ["dotnet", "InvenTrack.Api.dll"]
version: '3.8'
services:
api:
image: inventtrack-api
environment:
- ASPNETCORE_ENVIRONMENT=Production
ports:
- "8080:80"
Detecting Environments in Code
In Program.cs
var builder = WebApplication.CreateBuilder(args);
// Check environment during configuration
if (builder.Environment.IsDevelopment())
{
builder.Services.AddSwaggerGen();
}
var app = builder.Build();
// Check environment in middleware pipeline
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/error");
app.UseHsts();
}
if (app.Environment.IsProduction())
{
// Production-only configuration
}
if (app.Environment.IsStaging())
{
// Staging-only configuration
}
if (app.Environment.IsEnvironment("UAT"))
{
// Custom environment
}
In Controllers/Services
public class ProductsController : ControllerBase
{
private readonly IWebHostEnvironment _environment;
public ProductsController(IWebHostEnvironment environment)
{
_environment = environment;
}
[HttpGet("info")]
public IActionResult GetInfo()
{
return Ok(new
{
Environment = _environment.EnvironmentName,
IsDevelopment = _environment.IsDevelopment(),
ContentRootPath = _environment.ContentRootPath,
WebRootPath = _environment.WebRootPath
});
}
}
Available Methods
| Method | Returns True When |
|---|---|
IsDevelopment() |
Environment is "Development" |
IsStaging() |
Environment is "Staging" |
IsProduction() |
Environment is "Production" |
IsEnvironment("UAT") |
Environment matches the string (case-insensitive) |
Environment-Specific Configuration Files
ASP.NET Core automatically loads environment-specific configuration:
1. appsettings.json
2. appsettings.{Environment}.json (overrides #1)
3. User Secrets (Development only)
4. Environment Variables (overrides #1-3)
5. Command-line arguments (overrides #1-4)
Example: Different Database per Environment
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=InvenTrack;..."
},
"Logging": {
"LogLevel": {
"Default": "Information"
}
}
}
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=InvenTrack_Dev;..."
},
"Logging": {
"LogLevel": {
"Default": "Debug",
"Microsoft.EntityFrameworkCore": "Information"
}
}
}
{
// Connection string set via environment variable
"Logging": {
"LogLevel": {
"Default": "Warning",
"Microsoft.AspNetCore": "Error"
}
}
}
Environment-Specific Behavior
Development Environment
if (app.Environment.IsDevelopment())
{
// Detailed error pages
app.UseDeveloperExceptionPage();
// Swagger UI for API testing
app.UseSwagger();
app.UseSwaggerUI();
// Database error page
app.UseDatabaseErrorPage();
// Seed test data
using (var scope = app.Services.CreateScope())
{
var seeder = scope.ServiceProvider.GetRequiredService<DataSeeder>();
await seeder.SeedAsync();
}
}
Production Environment
if (app.Environment.IsProduction())
{
// Generic error handler
app.UseExceptionHandler("/error");
// HSTS (HTTP Strict Transport Security)
app.UseHsts();
// Response compression
app.UseResponseCompression();
// Response caching
app.UseResponseCaching();
}
Complete InvenTrack Example
var builder = WebApplication.CreateBuilder(args);
// Services configuration
builder.Services.AddControllers();
// Database - connection string varies by environment
builder.Services.AddDbContext<InvenTrackDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
// Development-only services
if (builder.Environment.IsDevelopment())
{
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
}
// Production-only services
if (builder.Environment.IsProduction())
{
builder.Services.AddResponseCompression();
builder.Services.AddResponseCaching();
}
var app = builder.Build();
// Middleware pipeline
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/error");
app.UseHsts();
}
if (app.Environment.IsProduction())
{
app.UseResponseCompression();
app.UseResponseCaching();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
Best Practices
1. Use Environment-Specific Configuration Files
appsettings.json- Shared defaultsappsettings.Development.json- Dev overrides (commit to Git)appsettings.Production.json- Minimal, no secrets (commit to Git)
2. Never Hardcode Environment Names
if (app.Environment.EnvironmentName == "Development") { ... }
if (app.Environment.IsDevelopment()) { ... }
3. Default to Production
If ASPNETCORE_ENVIRONMENT is not set, ASP.NET Core defaults to
Production. This is a safety featureβbetter to be too restrictive than
too permissive.
4. Use User Secrets in Development
dotnet user-secrets set "ConnectionStrings:DefaultConnection" "Server=localhost;..."
5. Use Environment Variables in Production
Set sensitive values (connection strings, API keys) via environment variables, not in configuration files.
6. Validate Environment-Specific Configuration
if (app.Environment.IsProduction())
{
var connString = builder.Configuration.GetConnectionString("DefaultConnection");
if (string.IsNullOrEmpty(connString))
{
throw new InvalidOperationException("Production connection string not configured");
}
}
Key Takeaways
- Environments let you configure apps differently per deployment
- Set via
ASPNETCORE_ENVIRONMENTenvironment variable - Built-in: Development, Staging, Production
launchSettings.jsonsets environment for local development- Detect with
IsDevelopment(),IsProduction(),IsStaging() - Inject
IWebHostEnvironmentto check environment in services appsettings.{Environment}.jsonoverrides base settings- Configuration precedence: JSON β User Secrets β Env Vars β Command Line
- Default is Production if not set (safety feature)
- Use User Secrets for development, Environment Variables for production
- Enable different features per environment (Swagger in Dev, HSTS in Prod)
- Validate critical configuration at startup
Congratulations! You've completed Part III: ASP.NET Core Basics. You now understand:
- β What ASP.NET Core is and its architecture
- β Building your first Web API
- β Program.cs and the middleware pipeline
- β Configuration with appsettings.json
- β The Options Pattern for strongly-typed config
- β Managing different environments
Next up: Part IV will dive into Dependency Injectionβ understanding service lifetimes, registering services, and building testable, maintainable applications. The journey to building InvenTrack continues! π