Introduction
ASP.NET Core uses a configuration system that reads from multiple providers (JSON files, environment variables, command-line args, user secrets). When configuration values are not loaded as expected, the issue is typically related to provider ordering (later providers override earlier ones), file path resolution, or the file not being copied to the output directory.
Symptoms
Configuration["ConnectionString"]returns null- Environment variable overrides are not applied
appsettings.Production.jsonvalues are not loaded in production- Configuration works locally but fails when deployed
IConfigurationsection is empty
Example debugging code showing the issue: ```csharp // This returns null unexpectedly var connString = builder.Configuration.GetConnectionString("Default");
// Debugging: check all loaded configuration var config = builder.Configuration; foreach (var provider in ((IConfigurationRoot)config).Providers) { Console.WriteLine($"Provider: {provider.GetType().Name}"); } ```
Common Causes
- JSON file not copied to output directory (Build Action not set correctly)
- Environment name not set, so environment-specific file not loaded
- File path incorrect when running from different working directory
- User secrets override JSON values in development
- Environment variables not formatted correctly for nested config
Step-by-Step Fix
- 1.Verify file is copied to output:
- 2.```xml
- 3.<!-- .csproj file -->
- 4.<ItemGroup>
- 5.<Content Include="appsettings.json" CopyToOutputDirectory="PreserveNewest" />
- 6.<Content Include="appsettings.*.json" CopyToOutputDirectory="PreserveNewest" />
- 7.</ItemGroup>
- 8.
` - 9.Check the environment name:
- 10.```bash
- 11.# Windows
- 12.echo %ASPNETCORE_ENVIRONMENT%
# Linux/macOS echo $ASPNETCORE_ENVIRONMENT
# Set for production export ASPNETCORE_ENVIRONMENT=Production ```
- 1.Verify configuration provider order:
- 2.```csharp
- 3.var builder = WebApplication.CreateBuilder(args);
// Default order (later overrides earlier): // 1. appsettings.json // 2. appsettings.{Environment}.json // 3. User Secrets (development only) // 4. Environment variables // 5. Command-line arguments
// Debug loaded providers var root = (IConfigurationRoot)builder.Configuration; foreach (var provider in root.Providers) { Console.WriteLine($"- {provider.GetType().Name}"); }
// Check a specific key Console.WriteLine($"DefaultConnection: {builder.Configuration.GetConnectionString("Default")}"); ```
- 1.Use environment variables for nested configuration:
- 2.```bash
- 3.# For nested JSON:
- 4.# {"Database":{"ConnectionString":"..."}}
- 5.# Use double underscore separator:
- 6.export Database__ConnectionString="Server=localhost;Database=mydb;"
# For arrays: # {"Smtp":{"Hosts":["smtp1.example.com","smtp2.example.com"]}} export Smtp__Hosts__0="smtp1.example.com" export Smtp__Hosts__1="smtp2.example.com" ```
- 1.Add custom configuration source:
- 2.```csharp
- 3.builder.Configuration
- 4..SetBasePath(Directory.GetCurrentDirectory())
- 5..AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
- 6..AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json",
- 7.optional: true, reloadOnChange: true)
- 8..AddEnvironmentVariables()
- 9..AddCommandLine(args);
// Validate required configuration if (string.IsNullOrEmpty(builder.Configuration.GetConnectionString("Default"))) { throw new InvalidOperationException( "ConnectionString 'Default' is not configured. " + "Set it in appsettings.json or via the ConnectionStrings__Default environment variable."); } ```
Prevention
- Always set
CopyToOutputDirectoryfor configuration files - Use
ASPNETCORE_prefix for environment variable overrides - Add startup validation for required configuration values
- Use
IOptions<T>with data annotations for validated configuration - Document all configuration keys and their expected sources
- Use
dotnet run -- --configuration:Debugto verify provider loading