Using Microsoft.Extensions.Configuration for Application Configuration in .NET Core

Nov 27, 2025 · Programming · 26 views · 7.8

Keywords: .NET Core Configuration | Microsoft.Extensions.Configuration | XML Configuration Provider | Options Pattern | Configuration Migration

Abstract: This article explores how to use Microsoft.Extensions.Configuration API for configuration management in .NET Core applications, covering various configuration sources including XML, JSON, and environment variables. It provides solutions for migrating traditional app.config to .NET Core, with practical code examples demonstrating configuration provider priorities, hierarchical data binding, and custom provider implementation to help developers build flexible and maintainable configuration systems.

Configuration System Overview

In the .NET Core ecosystem, the traditional System.Configuration.ConfigurationManager has been replaced by the Microsoft.Extensions.Configuration API. The new configuration system provides a more flexible and extensible architecture that supports seamless integration of multiple configuration sources.

Configuration Provider Priorities

Microsoft.Extensions.Configuration employs a hierarchical configuration model where configuration providers determine priority based on their addition order. Later-added providers have higher priority and can override settings from previous providers. The typical configuration source priority from highest to lowest is:

XML Configuration Provider Usage

While JSON has become the default configuration format in .NET Core, XML configuration remains well-supported. To use XML configuration, first install the Microsoft.Extensions.Configuration.Xml NuGet package:

dotnet add package Microsoft.Extensions.Configuration.Xml

Configure the XML provider in Program.cs:

var builder = WebApplication.CreateBuilder(args);
builder.Configuration
    .AddXmlFile("app.config", optional: true, reloadOnChange: true)
    .AddXmlFile($"app.{builder.Environment.EnvironmentName}.config", 
                optional: true, reloadOnChange: true);

Configuration Data Reading

Use the IConfiguration interface to read configuration values:

public class ConfigurationService
{
    private readonly IConfiguration _configuration;

    public ConfigurationService(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public string GetConnectionString()
    {
        return _configuration.GetConnectionString("sampleDatabase");
    }

    public string GetAppSetting(string key)
    {
        return _configuration[key];
    }
}

Options Pattern

The options pattern is the recommended approach for reading related configuration values, providing strongly-typed configuration access:

public class CustomOptions
{
    public const string SectionName = "custom";
    
    public string Key { get; set; } = string.Empty;
    public string Name { get; set; } = string.Empty;
    public int Age { get; set; }
}

// Register options service
builder.Services.Configure<CustomOptions>(
    builder.Configuration.GetSection(CustomOptions.SectionName));

// Use options
public class MyService
{
    private readonly CustomOptions _options;

    public MyService(IOptions<CustomOptions> options)
    {
        _options = options.Value;
    }

    public void ProcessConfiguration()
    {
        Console.WriteLine($"Key: {_options.Key}, Name: {_options.Name}, Age: {_options.Age}");
    }
}

Environment-Specific Configuration

Support for environment-specific configuration files such as appsettings.Development.json and appsettings.Production.json:

var builder = WebApplication.CreateBuilder(args);

// Automatically load environment-specific configuration
builder.Configuration
    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
    .AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", 
                optional: true, reloadOnChange: true);

Custom Configuration Section Handling

For complex custom configuration sections, implement configuration section classes:

public class CustomConfigurationSection
{
    public List<CustomConfiguration> CustomConfigurations { get; set; } = new();
}

public class CustomConfiguration
{
    public string Key { get; set; } = string.Empty;
    public string Name { get; set; } = string.Empty;
    public int Age { get; set; }
}

// Bind configuration
var customSection = new CustomConfigurationSection();
builder.Configuration.GetSection("custom").Bind(customSection);

Configuration Validation

Use data annotations for configuration validation:

using System.ComponentModel.DataAnnotations;

public class ValidatedOptions
{
    [Required]
    [MinLength(1)]
    public string RequiredSetting { get; set; } = string.Empty;
    
    [Range(1, 100)]
    public int NumericSetting { get; set; }
}

// Validate configuration
var options = new ValidatedOptions();
builder.Configuration.GetSection("validated").Bind(options);

var validationContext = new ValidationContext(options);
var validationResults = new List<ValidationResult>();
bool isValid = Validator.TryValidateObject(options, validationContext, validationResults, true);

Configuration Reloading

Support for dynamic reloading of configuration files:

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

// Use IOptionsSnapshot to get latest configuration
public class ConfigAwareService
{
    private readonly IOptionsSnapshot<CustomOptions> _optionsSnapshot;

    public ConfigAwareService(IOptionsSnapshot<CustomOptions> optionsSnapshot)
    {
        _optionsSnapshot = optionsSnapshot;
    }

    public void UseCurrentConfig()
    {
        var currentOptions = _optionsSnapshot.Value;
        // Use current configuration
    }
}

Migration Recommendations

Recommendations for migrating from traditional app.config to the new configuration system:

  1. Convert XML configuration to JSON format for better performance and support
  2. Use options pattern instead of direct ConfigurationManager calls
  3. Leverage environment-specific configuration instead of configuration transforms
  4. Consider using user secrets for sensitive data management
  5. Implement configuration validation to ensure configuration integrity

Best Practices

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.