ASP.NET - Custom Configuration Sources

Custom configuration sources allow an application to load settings from places other than files and environment variables. Instead of relying only on JSON or command line input, the app can pull configuration from databases, APIs, encrypted stores or any external service.


Purpose of Custom Sources
Default providers may not cover every scenario. Some systems keep settings in secure vaults or centralized stores shared across applications. A custom source enables reading values from those locations without copying data into files. This ensures configuration stays current and consistent.


How a Custom Source Works
A custom source supplies a provider that loads key-value pairs into the configuration system. The provider chooses where the data comes from and how often it refreshes. Once loaded, the values behave like normal configuration keys and are available through IConfiguration.


Creating a Custom Provider
A provider inherits from ConfigurationProvider and overrides the Load method. The Load method retrieves configuration values from the target location, converts them into a dictionary and stores them in the internal data collection. The application can then access the keys normally.


Registering the Source in the Builder
After writing the provider, register it inside the configuration pipeline. The builder adds the new provider, and its values appear in the final configuration tree. If placed later in the chain, it overrides earlier values when using the same keys.


Why Custom Sources Help
Custom sources support flexible deployment. Apps can pull secrets from vaults, dynamic settings from databases or tenant-specific values for multi-tenant systems. They keep code unchanged even when configuration strategies evolve.


Example

// Custom source and provider
public class DbConfigSource : IConfigurationSource
{
    public IConfigurationProvider Build(IConfigurationBuilder builder)
        => new DbConfigProvider();
}

public class DbConfigProvider : ConfigurationProvider
{
    public override void Load()
    {
        Data = new Dictionary<string, string>
        {
            ["FeatureZ:Enabled"] = "true"
        };
    }
}
// Program.cs
var builder = WebApplication.CreateBuilder(args);

builder.Configuration.Add(new DbConfigSource());

var app = builder.Build();

app.MapGet("/", () => builder.Configuration["FeatureZ:Enabled"]);

app.Run();

Result
The app loads FeatureZ:Enabled from the custom provider instead of JSON or environment files.