.NET Environment Variables
Environment variables provide a flexible way to store configuration settings for your applications. In .NET, they serve as a crucial mechanism for managing application settings across different deployment environments without changing your code.
Introduction to Environment Variables
Environment variables are name-value pairs that are part of the environment in which a process runs. They allow you to:
- Store configuration outside your application code
- Change application behavior without modifying code
- Maintain different settings across development, testing, and production environments
- Store sensitive information like connection strings securely
In the .NET ecosystem, environment variables are commonly used for configuration management, especially in modern application patterns like containerization and cloud-native applications.
Accessing Environment Variables in .NET
.NET provides several ways to access environment variables in your applications.
Using the Environment Class
The most straightforward way to access environment variables is through the Environment
class in the System
namespace.
using System;
string databaseConnection = Environment.GetEnvironmentVariable("DATABASE_CONNECTION");
Console.WriteLine($"Connection string: {databaseConnection ?? "Not set"}");
The GetEnvironmentVariable
method returns null
if the variable doesn't exist, so you should always check for null values or provide defaults.
Process-Level vs. Machine-Level Variables
.NET allows you to specify the scope when retrieving environment variables:
// Get user-level (current process) environment variable
string userVariable = Environment.GetEnvironmentVariable(
"USER_PREFERENCE",
EnvironmentVariableTarget.Process);
// Get machine-level environment variable
string machineVariable = Environment.GetEnvironmentVariable(
"SHARED_SETTING",
EnvironmentVariableTarget.Machine);
// Get user-specific environment variable
string userSpecificVariable = Environment.GetEnvironmentVariable(
"USER_PROFILE_PATH",
EnvironmentVariableTarget.User);
Setting Environment Variables
You can set environment variables programmatically in your .NET applications:
// Set a process-level environment variable
Environment.SetEnvironmentVariable("APP_MODE", "Development", EnvironmentVariableTarget.Process);
// Set a machine-level environment variable (requires admin privileges)
// Environment.SetEnvironmentVariable("GLOBAL_SETTING", "Value", EnvironmentVariableTarget.Machine);
// Get and display the variable we just set
Console.WriteLine($"App Mode: {Environment.GetEnvironmentVariable("APP_MODE")}");
Output:
App Mode: Development
Remember that setting machine-level or user-level variables requires appropriate permissions and will persist beyond the lifetime of your application.
Environment Variables and Configuration in .NET Core/.NET 5+
Modern .NET applications use the configuration system that automatically pulls values from environment variables.
Basic Configuration Setup
using Microsoft.Extensions.Configuration;
var configuration = new ConfigurationBuilder()
.AddEnvironmentVariables()
.Build();
// Access configuration values
string logLevel = configuration["LOG_LEVEL"];
Console.WriteLine($"Log level: {logLevel ?? "Not set"}");
Configuration with Hierarchical Values
Environment variables can represent hierarchical configuration by using double underscores (__
):
// Environment variable: ConnectionStrings__DefaultConnection=server=localhost;database=mydb
var configuration = new ConfigurationBuilder()
.AddEnvironmentVariables()
.Build();
string connectionString = configuration["ConnectionStrings:DefaultConnection"];
Console.WriteLine($"Connection string: {connectionString}");
Environment Variables in ASP.NET Core
In ASP.NET Core applications, environment variables are integrated into the configuration system by default.
var builder = WebApplication.CreateBuilder(args);
// Configuration is already set up to use environment variables
var logLevel = builder.Configuration["Logging:LogLevel:Default"];
Console.WriteLine($"Default log level: {logLevel}");
// You can also access environment variables directly
string aspNetEnv = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
Console.WriteLine($"ASP.NET Core environment: {aspNetEnv ?? "Not set"}");
The Special ASPNETCORE_ENVIRONMENT Variable
This special environment variable determines the runtime environment of your ASP.NET Core application:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => {
if (app.Environment.IsDevelopment())
{
return "Running in Development environment";
}
else if (app.Environment.IsProduction())
{
return "Running in Production environment";
}
else if (app.Environment.IsStaging())
{
return "Running in Staging environment";
}
else
{
return $"Running in {app.Environment.EnvironmentName} environment";
}
});
app.Run();
Common values for ASPNETCORE_ENVIRONMENT
are:
- Development
- Staging
- Production
Using Environment Variables in Docker Containers
When deploying .NET applications in Docker containers, environment variables become particularly important:
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY ./bin/Release/net6.0/publish/ .
# Set environment variables in the container
ENV ASPNETCORE_ENVIRONMENT=Production
ENV ConnectionStrings__DefaultDatabase="Server=db;Database=myapp;User=sa;Password=YourPassword;"
ENTRYPOINT ["dotnet", "MyApp.dll"]
When running the container:
docker run -p 8080:80 -e "FEATURE_FLAGS__ENABLE_BETA=true" myapp:latest
User Secrets vs. Environment Variables
For local development, .NET provides a user secrets mechanism as an alternative to environment variables:
// Example with user secrets (development only)
var builder = WebApplication.CreateBuilder(args);
// For development, secrets.json is used
if (builder.Environment.IsDevelopment())
{
builder.Configuration.AddUserSecrets<Program>();
}
string apiKey = builder.Configuration["ApiKeys:ExternalService"];
However, in production environments, you would typically use environment variables instead of user secrets.
Environment Variables Best Practices
- Naming conventions: Use uppercase names with underscores for clarity (e.g.,
DATABASE_CONNECTION
) - Don't commit sensitive values: Never commit actual environment variable values to source control
- Use prefixes: Prefix environment variables with your application name to avoid conflicts (e.g.,
MYAPP_DATABASE_URL
) - Provide defaults: Always handle missing environment variables gracefully
- Documentation: Document all environment variables your application uses
Real-World Example: Complete Configuration System
Here's a more complete example showing how to build a robust configuration system using environment variables:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
// Create a configuration builder
var configBuilder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
.AddEnvironmentVariables()
.AddCommandLine(args);
// For development environment, add user secrets
if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development")
{
configBuilder.AddUserSecrets<Program>();
}
IConfiguration configuration = configBuilder.Build();
// Example: Read database configuration
var databaseConfig = new DatabaseConfig
{
ConnectionString = configuration["Database:ConnectionString"],
MaxRetryCount = int.Parse(configuration["Database:MaxRetryCount"] ?? "3"),
EnableDetailedLogging = bool.Parse(configuration["Database:EnableDetailedLogging"] ?? "false")
};
Console.WriteLine($"Database Configuration:");
Console.WriteLine($"Connection: {databaseConfig.ConnectionString ?? "Not set"}");
Console.WriteLine($"Max Retry: {databaseConfig.MaxRetryCount}");
Console.WriteLine($"Detailed Logging: {databaseConfig.EnableDetailedLogging}");
// Class to hold configuration
public class DatabaseConfig
{
public string ConnectionString { get; set; }
public int MaxRetryCount { get; set; }
public bool EnableDetailedLogging { get; set; }
}
Summary
Environment variables provide a powerful and flexible way to configure .NET applications across different environments. Key takeaways include:
- Environment variables allow configuration without code changes
- .NET provides multiple ways to access environment variables
- Modern .NET applications integrate environment variables into the configuration system
- Environment variables are especially important in containerized and cloud environments
- Following naming and usage best practices helps maintain clean configuration management
By using environment variables effectively, you can build .NET applications that are more maintainable, secure, and adaptable to different deployment scenarios.
Additional Resources
- Microsoft Docs: Configuration in ASP.NET Core
- Environment Variables in .NET SDK
- Safe storage of app secrets in development in ASP.NET Core
Practice Exercises
- Create a console application that reads different types of environment variables and provides default values when they're not present.
- Build a simple ASP.NET Core web API that changes its behavior based on environment variables.
- Set up a Docker container for a .NET application, passing different environment variables to change the application behavior.
- Create a configuration system that combines environment variables with appsettings.json files, with environment variables taking precedence.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)