# Configuration Options for ASP.NET Core Applications: Provider Pipeline and Patterns

> Explore ASP.NET Core configuration options, mastering provider pipelines like JSON, environment variables, and secrets for flexible application settings and POCO binding.

- Repository: [.NET Platform/aspnetcore](https://github.com/dotnet/aspnetcore)
- Tags: deep-dive
- Published: 2026-07-13

---

**ASP.NET Core applications configure settings through a hierarchical pipeline of providers—including JSON files, environment variables, command-line arguments, and user secrets—that merge into an `IConfiguration` object supporting reload-on-change and POCO binding.**

The `dotnet/aspnetcore` repository implements a flexible configuration system built on `Microsoft.Extensions.Configuration` abstractions. Understanding the available configuration options for ASP.NET Core applications allows developers to externalize settings per environment without code changes, leveraging providers that automatically reload or bind to strongly-typed objects.

## Built-in Configuration Providers

The configuration pipeline is constructed by `IHostBuilder` or `WebApplicationBuilder` (in minimal-API projects) through a series of **configuration providers**. Each provider implements `IConfigurationProvider` and supplies key-value pairs that the `ConfigurationRoot` merges into a single hierarchical view.

### JSON File Provider

The most common source for settings is [`appsettings.json`](https://github.com/dotnet/aspnetcore/blob/main/appsettings.json) combined with environment-specific variants. In [`Program.cs`](https://github.com/dotnet/aspnetcore/blob/main/Program.cs), the builder adds these via `AddJsonFile`:

```csharp
builder.Configuration
       .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
       .AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", 
                    optional: true, reloadOnChange: true);

```

When `reloadOnChange` is set to `true`, the framework uses file watchers to trigger configuration updates without restarting the application.

### Environment Variables Provider

Operating-system environment variables are loaded via `AddEnvironmentVariables()`:

```csharp
builder.Configuration.AddEnvironmentVariables();

```

This provider captures variables such as `ASPNETCORE_URLS` and maps them to configuration keys. Because environment variables are static snapshots, they do not support reload-on-change.

### Command-Line Arguments Provider

Arguments passed to `dotnet run` are bound to keys using the `AddCommandLine` method:

```csharp
builder.Configuration.AddCommandLine(args);

```

Syntax such as `--urls https://localhost:5001` overrides earlier provider values.

### User Secrets Provider

During development, sensitive data is stored outside the repository in [`secrets.json`](https://github.com/dotnet/aspnetcore/blob/main/secrets.json). The `AddUserSecrets<T>()` extension (which relies on `ReadableJsonConfigurationSource` in [`src/Tools/dotnet-user-secrets/src/Internal/ReadableJsonConfigurationSource.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Tools/dotnet-user-secrets/src/Internal/ReadableJsonConfigurationSource.cs)) loads these values:

```csharp
if (builder.Environment.IsDevelopment())
{
    builder.Configuration.AddUserSecrets<Program>();
}

```

### Key-per-File Provider

Containerized deployments often mount secrets as individual files. The `KeyPerFileConfigurationProvider` (implemented in [`src/Configuration/KeyPerFile/src/KeyPerFileConfigurationProvider.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Configuration/KeyPerFile/src/KeyPerFileConfigurationProvider.cs)) treats each filename as a key and the file content as the value:

```csharp
builder.Configuration.AddKeyPerFile("/etc/config", optional: true);

```

When file watchers are enabled, this provider supports reload-on-change, making it ideal for Kubernetes secrets.

### In-Memory Collection

For programmatic defaults or testing, use `AddInMemoryCollection`:

```csharp
builder.Configuration.AddInMemoryCollection(new[] 
{ 
    new KeyValuePair<string, string>("Key", "Value") 
});

```

## Configuration Precedence and Overrides

Providers are registered in a specific order, and the `ConfigurationRoot` merges them such that **later providers override earlier ones**. The typical registration order is:

1. JSON files (base then environment-specific)
2. User secrets (Development only)
3. Environment variables
4. Command-line arguments

This precedence model allows production deployments to override development settings via environment variables or command-line switches without modifying code.

## Hierarchical Keys and Options Binding

Configuration keys use a colon (`:`) separator to express hierarchy (e.g., `Logging:LogLevel:Default`). The framework can bind sections directly to POCO classes using the **Options pattern**:

```csharp
public class MyOptions
{
    public string ConnectionString { get; set; } = default!;
    public int MaxItems { get; set; }
}

// In Program.cs
builder.Services.Configure<MyOptions>(builder.Configuration.GetSection("MyOptions"));

```

Alternatively, access values directly via `IConfiguration`:

```csharp
public class HomeController : Controller
{
    private readonly IConfiguration _config;
    public HomeController(IConfiguration config) => _config = config;

    public IActionResult Index()
    {
        var maxItems = _config.GetValue<int>("MyOptions:MaxItems");
        return Content($"Max items = {maxItems}");
    }
}

```

The binding process respects data-type conversion, collections, and nested objects automatically.

## Reload on Change

Providers that support change notifications (JSON files and Key-per-File) emit an `IChangeToken`. When `reloadOnChange` is enabled, the configuration root rebuilds its snapshot, and services consuming `IOptionsSnapshot<T>` or `IConfiguration` receive updated values immediately. Static providers such as environment variables and command-line arguments do not support this behavior.

## Server-Specific Configuration (Kestrel)

Server-level settings for Kestrel are also expressed through the configuration system. The `KestrelServerOptions.Configure(IConfiguration)` extension reads the `Kestrel` section from the merged configuration. The loader in [`src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs) uses a dedicated `ConfigurationReader` to parse endpoints and certificates:

```json
{
  "Kestrel": {
    "Endpoints": {
      "Http": { "Url": "http://0.0.0.0:5000" },
      "Https": {
        "Url": "https://0.0.0.0:5001",
        "Certificate": {
          "Path": "cert.pfx",
          "Password": "secret"
        }
      }
    }
  }
}

```

This allows operators to define URLs and TLS certificates via JSON, environment variables, or command-line arguments without touching code.

## Summary

- **ASP.NET Core** builds configuration from a chain of providers registered on `WebApplicationBuilder` or `IHostBuilder`.
- **Built-in providers** include JSON files, environment variables, command-line arguments, user secrets, and key-per-file (for container secrets).
- **Precedence** is determined by registration order; later providers override earlier values.
- **Hierarchical keys** use colons and bind to POCOs via `services.Configure<T>()` or `IConfiguration.GetValue<T>()`.
- **Reload-on-change** is supported by JSON and Key-per-File providers, enabling runtime updates without restarts.
- **Kestrel settings** are loaded from the `Kestrel` configuration section via `KestrelConfigurationLoader`.

## Frequently Asked Questions

### What is the default configuration order in ASP.NET Core?

The default order is JSON files ([`appsettings.json`](https://github.com/dotnet/aspnetcore/blob/main/appsettings.json) then environment-specific), user secrets (Development only), environment variables, and finally command-line arguments. This sequence ensures that command-line arguments override environment variables, which override file-based settings.

### How do I reload configuration automatically when appsettings.json changes?

Pass `reloadOnChange: true` to `AddJsonFile`. The framework monitors the file for modifications and updates the `IConfiguration` snapshot automatically. Services using `IOptionsSnapshot<T>` will receive the new values on the next request.

### Can I store secrets securely in ASP.NET Core?

Yes. Use the **User Secrets** provider (`AddUserSecrets<Program>()`) during development to keep sensitive data out of source control. For production, use environment variables, Azure Key Vault (via a custom provider), or container secret mounts with the **Key-per-File** provider.

### How do I access nested configuration values in a controller?

Inject `IConfiguration` into the controller constructor and use the colon-separated key path, or bind a section to a POCO using `services.Configure<MyOptions>(Configuration.GetSection("SectionName"))` and inject `IOptions<MyOptions>`.