Configuration in ASP.NET Core: appsettings.json, IConfiguration, and IOptions Explained
Modern applications rely on configuration to store values that can change without modifying the source code. Examples include database connection strings, API keys, email server settings, logging options, and feature flags.
ASP.NET Core provides a powerful and flexible configuration system that lets you read settings from multiple sources while keeping your application clean, secure, and easy to maintain.
In this article, you’ll learn:
- What configuration is
- Why configuration is important
- Configuration providers in ASP.NET Core
- Using
appsettings.json - Reading values with
IConfiguration - Using the
IOptionspattern - Configuration precedence
- Best practices
What Is Configuration?
Configuration is the process of storing application settings outside of your source code.
Instead of writing values directly into your classes, you place them in configuration files or other configuration providers.
For example, instead of writing:
string connectionString = "Server=.;Database=MyDb;Trusted_Connection=True;";
Store it in a configuration file:
{
"ConnectionStrings": {
"DefaultConnection": "Server=.;Database=MyDb;Trusted_Connection=True;"
}
}
Your application can then read this value at runtime.
This approach makes it easy to change settings without recompiling your application.
Why Use Configuration?
Using configuration offers several benefits:
- Keeps sensitive information out of your code.
- Makes applications easier to deploy across different environments.
- Allows different settings for Development, Testing, and Production.
- Improves maintainability.
- Supports multiple configuration sources.
Configuration Providers in ASP.NET Core
ASP.NET Core can load configuration from multiple providers, including:
appsettings.jsonappsettings.{Environment}.json- Environment variables
- Command-line arguments
- User Secrets (development)
- Azure Key Vault
- Azure App Configuration
- In-memory collections
All these providers are combined into a single configuration system.
The appsettings.json File
The primary configuration file in ASP.NET Core is appsettings.json.
Example:
{
"ConnectionStrings": {
"DefaultConnection": "Server=.;Database=ShopDb;Trusted_Connection=True;"
},
"EmailSettings": {
"Host": "smtp.gmail.com",
"Port": 587,
"Username": "admin@example.com",
"Password": "password"
},
"Application": {
"Name": "My Store",
"Version": "1.0"
}
}
This file contains configuration values organized into sections.
Configuration Sections
Configuration values are grouped into sections.
Example:
{
"Application": {
"Name": "Inventory System",
"Version": "2.1",
"Company": "ABC Technologies"
}
}
To access the Application section:
builder.Configuration.GetSection("Application");
Reading Configuration Using IConfiguration
ASP.NET Core automatically registers IConfiguration with the Dependency Injection container.
You can inject it into any service or controller.
public class ProductService
{
private readonly IConfiguration _configuration;
public ProductService(IConfiguration configuration)
{
_configuration = configuration;
}
}
Read a simple value:
string appName = _configuration["Application:Name"];
Read another value:
string version = _configuration["Application:Version"];
Notice that nested values are separated using a colon (:).
Reading Connection Strings
ASP.NET Core provides a helper method for connection strings.
Example:
{
"ConnectionStrings": {
"DefaultConnection": "Server=.;Database=ShopDb;Trusted_Connection=True;"
}
}
Read it like this:
string connectionString =
_configuration.GetConnectionString("DefaultConnection");
This is the recommended approach when working with Entity Framework Core.
Registering DbContext
A common use case is configuring Entity Framework Core.
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(
builder.Configuration.GetConnectionString("DefaultConnection")));
Now your database connection can be changed without modifying the code.
Environment-Specific Configuration
Different environments often require different settings.
ASP.NET Core supports this automatically.
appsettings.json
appsettings.Development.json
appsettings.Staging.json
appsettings.Production.json
For example:
appsettings.json
{
"Application": {
"Name": "Inventory System"
}
}
appsettings.Development.json
{
"Application": {
"Name": "Inventory System (Development)"
}
}
When the application runs in the Development environment, the values from appsettings.Development.json override those in appsettings.json.
Using the IOptions Pattern
While IConfiguration is useful, repeatedly accessing configuration values throughout your application can make your code harder to maintain.
The recommended approach is to bind configuration sections to strongly typed classes using the IOptions pattern.
Step 1: Create a Settings Class
public class EmailSettings
{
public string Host { get; set; } = string.Empty;
public int Port { get; set; }
public string Username { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
}
Step 2: Add Configuration
{
"EmailSettings": {
"Host": "smtp.gmail.com",
"Port": 587,
"Username": "admin@example.com",
"Password": "password"
}
}
Step 3: Register the Configuration
In Program.cs:
builder.Services.Configure<EmailSettings>(
builder.Configuration.GetSection("EmailSettings"));
Step 4: Inject IOptions
using Microsoft.Extensions.Options;
public class EmailService
{
private readonly EmailSettings _settings;
public EmailService(IOptions<EmailSettings> options)
{
_settings = options.Value;
}
public void Send()
{
Console.WriteLine(_settings.Host);
}
}
Your configuration is now strongly typed, making your code easier to read and reducing the chance of errors caused by mistyped configuration keys.
IConfiguration vs IOptions
| Feature | IConfiguration | IOptions |
|---|---|---|
| Access values by key | ✔️ | ❌ |
| Strongly typed | ❌ | ✔️ |
| Easy to use | ✔️ | ✔️ |
| Best for many related settings | ❌ | ✔️ |
| Recommended for application settings | ❌ | ✔️ |
When to Use IConfiguration
Use IConfiguration when:
- Reading a few individual values.
- Accessing connection strings.
- Reading values during application startup.
When to Use IOptions
Use IOptions when:
- Working with groups of related settings.
- Creating reusable services.
- Building larger applications where maintainability is important.
Configuration Precedence
If the same configuration key exists in multiple providers, ASP.NET Core uses the value from the provider with the highest priority.
A common order of precedence is:
appsettings.jsonappsettings.{Environment}.json- User Secrets (Development)
- Environment Variables
- Command-line Arguments
This allows you to keep default values in appsettings.json while overriding them for specific environments or deployments.
Best Practices
- Store configuration outside your source code whenever possible.
- Use
IOptionsfor groups of related settings. - Keep
appsettings.jsonorganized with logical sections. - Use environment-specific configuration files for different deployments.
- Avoid storing secrets such as passwords or API keys in
appsettings.jsonfor production. Instead, use secure solutions like User Secrets during development and services such as Azure Key Vault in production. - Use meaningful section names to make configuration easy to understand.
- Access connection strings using
GetConnectionString()instead of reading them as plain keys.
Common Mistakes
Hardcoding Values
Avoid:
string apiUrl = "https://api.example.com";
Prefer:
{
"ApiSettings": {
"BaseUrl": "https://api.example.com"
}
}
Using IConfiguration Everywhere
If multiple classes need the same configuration section, bind it once with IOptions instead of repeatedly reading individual keys.
Committing Secrets to Source Control
Never commit production passwords, API keys, or connection strings to your repository. Use secure secret management solutions appropriate for your environment.
Summary
ASP.NET Core’s configuration system makes it easy to manage application settings from multiple sources while keeping your code clean and maintainable.
appsettings.jsonstores your application’s configuration.IConfigurationprovides flexible access to configuration values.IOptionsbinds configuration to strongly typed classes, making your code more robust and easier to maintain.
By combining these features with environment-specific configuration files and secure secret management, you can build applications that are easier to configure, deploy, and maintain across development, testing, and production environments.


