ASP.NET Core  

Modern Configuration System in ASP.NET Core

Modern applications need flexible, secure, and environment-aware configuration systems. ASP.NET Core provides one of the most powerful and extensible configuration frameworks in any web platform today. The modern configuration system is designed to work across environments, support multiple formats, enable strong typing, and integrate seamlessly with cloud platforms and secret management services.

Unlike the older .NET Framework approach that mainly relied on a single web.config file, ASP.NET Core's configuration system is built on a provider-based model. This allows configuration values to come from many different sources such as JSON files, environment variables, command-line arguments, secret stores, and cloud configuration services.

ModernConfiguration

Why a Modern Configuration System?

Earlier systems had limitations:

  • Single configuration file

  • Hard to override values

  • No environment separation

  • No encryption support

  • Poor cloud compatibility

ASP.NET Core solves these through:

  • Multiple configuration providers

  • Hierarchical key-value structure

  • Environment-based configuration

  • Dependency injection support

  • Strongly typed settings

  • Secure secret management

Configuration Providers (Sources)

ASP.NET Core reads configuration from many providers in a specific order of priority:

  1. appsettings.json

  2. appsettings.{Environment}.json

  3. User Secrets (Development only)

  4. Environment Variables

  5. Command-line Arguments

Later providers override earlier ones.

appsettings.json Example

{"Application": {
    "Name": "DemoApp",
    "Version": "2.1"},"Database": {
    "ConnectionString": "Server=.;Database=DemoDB;Trusted_Connection=True;",
    "Timeout": 30},"Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning"
    }}}

Reading Configuration Values

Basic Example

var builder = WebApplication.CreateBuilder(args);

string appName = builder.Configuration["Application:Name"];
string connectionString = builder.Configuration["Database:ConnectionString"];

The colon (:) represents hierarchy inside JSON.

Environment-Specific Configuration

Create files:

  • appsettings.Development.json

  • appsettings.Staging.json

  • appsettings.Production.json

Example

{"Database": {
    "ConnectionString": "Server=DEV;Database=TestDB"}}

ASP.NET Core automatically loads the correct configuration based on:

ASPNETCORE_ENVIRONMENT=Development

Strongly Typed Configuration (Options Pattern)

Instead of accessing configuration with strings, map settings to C# classes.

Step 1: Create a settings class

public class DatabaseSettings
{
    public string ConnectionString { get; set; }
    public int Timeout { get; set; }
}

Step 2: Bind configuration

builder.Services.Configure<DatabaseSettings>(
    builder.Configuration.GetSection("Database"));

Step 3: Inject into services/controllers

public class DataService
{
    private readonly DatabaseSettings _settings;

    public DataService(IOptions<DatabaseSettings> options)
    {
        _settings = options.Value;
    }
}

Multiple Configuration Files

Load additional configuration files:

builder.Configuration
       .AddJsonFile("features.json", optional: true)
       .AddJsonFile("pricing.json", optional: true);

Enables module-based configuration management.

Environment Variables

Environment variables override json values.

Example

Set:

Database__Timeout=60

Double underscores (__) map to JSON sections.

Read it like:

var timeout = builder.Configuration["Database:Timeout"];

Command Line Configuration

dotnet run --Database:Timeout=100

This overrides everything.

User Secrets (for Development)

Avoid storing passwords in code:

dotnet user-secrets init
dotnet user-secrets set "Database:ConnectionString" "SecureValue"

Read it same as configuration:

builder.Configuration["Database:ConnectionString"];

Secrets never get committed.

Secure Secrets in Production

In production, integrate secret managers:

  • Azure Key Vault

  • AWS Secrets Manager

  • HashiCorp Vault

Example (Azure Key Vault):

builder.Configuration.AddAzureKeyVault(
    new Uri("https://myvault.vault.azure.net/"),
    new DefaultAzureCredential());

Configuration Reloading

Reload on change:

builder.Configuration
       .AddJsonFile("appsettings.json", optional:false, reloadOnChange:true);

File changes update configuration without restarting application.

Configuration in Minimal APIs

var app = builder.Build();

app.MapGet("/config", (IConfiguration config) =>
{
    return config["Application:Name"];
});

Validation of Configuration

Prevent startup from failing silently:

builder.Services
    .AddOptions<DatabaseSettings>()
    .BindConfiguration("Database")
    .ValidateDataAnnotations()
    .Validate(s => s.Timeout > 10, "Timeout too short");

IOptions Variants

TypePurpose
IOptionsSingleton access
IOptionsSnapshotScoped per request
IOptionsMonitorLive reloading

Example:

public class MyService
{
    public MyService(IOptionsMonitor<DatabaseSettings> options)
    {
        options.OnChange(updated =>
        {
            Console.WriteLine("Settings updated");
        });
    }
}

Using Configuration in Middleware

app.Use(async (context, next) =>
{
    var mode = context.RequestServices.GetRequiredService<IConfiguration>()["Mode"];
    if (mode == "Maintenance")
    {
        context.Response.StatusCode = 503;
        return;
    }

    await next();
});

Best Practices

✅ Never store secrets in Git
✅ Use options pattern
✅ Separate configs by environment
✅ Use environment variables in containers
✅ Validate your config on startup
✅ Use secret managers
✅ Avoid magic strings
✅ Use reload where applicable

Real-World SaaS Practice

In SaaS:

  • Feature flags from config

  • Plan-based limits from config

  • API keys from vault

  • Email gateways from config

  • Tenant rules from config

Configuration becomes operational control, not just app settings.

Conclusion

ASP.NET Core’s modern configuration system is built for real-world applications that need flexibility, security, and scalability. From local development to enterprise cloud environments, it enables developers to manage settings without rewriting code or redeploying applications.

Whether you are building a simple API or a large SaaS application, mastering the configuration system ensures secure deployments, easier debugging, and smoother operations.