ConfigurationPlaceholders 2.0.1
dotnet add package ConfigurationPlaceholders --version 2.0.1
NuGet\Install-Package ConfigurationPlaceholders -Version 2.0.1
<PackageReference Include="ConfigurationPlaceholders" Version="2.0.1" />
paket add ConfigurationPlaceholders --version 2.0.1
#r "nuget: ConfigurationPlaceholders, 2.0.1"
// Install ConfigurationPlaceholders as a Cake Addin #addin nuget:?package=ConfigurationPlaceholders&version=2.0.1 // Install ConfigurationPlaceholders as a Cake Tool #tool nuget:?package=ConfigurationPlaceholders&version=2.0.1
ConfigurationPlaceholders
Adds support for placeholders in any configuration source (e.g. appsettings.json).
Getting started
Install the ConfigurationPlaceholders package from NuGet:
Package manager:
Install-Package ConfigurationPlaceholders
Or via the .NET CLI
dotnet add package ConfigurationPlaceholders
You can add ConfigurationPlaceholders to your project with the AddConfigurationPlaceholders
extension method.
var builder = WebApplication.CreateBuilder( args );
builder
.AddConfigurationPlaceholders( new InMemoryPlaceholderResolver( new Dictionary<String, String?>
{
{ "FQDN", fullDomainName }
} ) );
This will replace the placeholder ${FQDN}
with the fully qualified name of the machine running the application.
Placeholder in the appsettings.json
:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"CertificateSubject": "${FQDN}"
}
You can specify any number of placeholder resolvers IPlaceholderResolver
in the call to AddConfigurationPlaceholders
.
Later added placeholder resolvers IPlaceholderResolver
will override values from before added placeholder resolvers IPlaceholderResolver
.
Placeholder verification
By default ConfigurationPlaceholders will check if values are provided for all placeholders. If there are any missing placeholder values a ConfigurationPlaceholderMissingException
will be thrown.
You can change this behavior by passing another MissingPlaceholderValueStrategy
to AddConfigurationPlaceholders
.
The following strategies are available:
VerifyAllAtStartup (default)
Will check if values are provided for all placeholders. If there are any missing placeholder values a ConfigurationPlaceholderMissingException
will be thrown.
Throw
You can think of this one as a lazy execution version of VerifyAllAtStartup
.
A ConfigurationPlaceholderMissingException
will be thrown when a configuration entry with a missing placeholder value is being accessed. If the value never gets accessed, no exception will be thrown.
UseEmptyValue
Placeholders for which no value is provided will be replaced with an empty string.
"Hello, ${MissingValue}"
will result in "Hello, "
IgnorePlaceholder
Placeholders for which no value is provided will not be replaced. The resulting value will still contain the placeholder.
"Hello, ${MissingValue}"
will result in "Hello, ${MissingValue}"
Examples
You can find some examples using ConfigurationPlaceholders here
Available placeholder resolvers IPlaceholderResolver
InMemoryPlaceholderResolver
Resolves placeholder values from an in-memory lookup. Works similar like the AddInMemoryCollection
configuration source.
new InMemoryPlaceholderResolver( new Dictionary<String, String?>
{
{ "ApplicationName", Assembly.GetExecutingAssembly().GetName().Name },
{ "ApplicationVersion", Assembly.GetExecutingAssembly().GetName().Version!.ToString() }
} )
CallbackPlaceholderResolver
Resolves placeholder values by invoking user provided value factories.
new CallbackPlaceholderResolver( new Dictionary<String, Func<String?>>
{
{ "Time", () => DateTime.Now.ToString( "HH:mm:ss.fff" ) }
} )
ConfigurationPlaceholderResolver
Searches for values in all configuration sources matching the placeholder key.
new ConfigurationPlaceholderResolver()
In this example LocalDb
is build based on other values in appsettings.json
:
{
"Lookup": {
"DataDir": "X:/Temp/",
"DbDir": "${Lookup:DataDir}db/"
},
"LocalDb": "${Lookup:DbDir}store.db"
}
EnvironmentVariableResolver
Resolves placeholder values by searching for environment variables matching the placeholder key. The search is performed in this priority order:
- EnvironmentVariableTarget.Process
- EnvironmentVariableTarget.User
- EnvironmentVariableTarget.Machine
new EnvironmentVariableResolver()
Custom providers
You can add your own placeholder resolvers by implementing IPlaceholderResolver
.
Potential sources could be REST APIs, files, secret stores etc...
How to add ConfigurationPlaceholders to your application
Different application setups require different ways to add ConfigurationPlaceholders.
WebApplication / minimal API
var builder = WebApplication.CreateBuilder( args );
builder
.AddConfigurationPlaceholders( new InMemoryPlaceholderResolver( new Dictionary<String, String?>
{
{ "FQDN", fullDomainName }
} ) );
IHostBuilder / "old" ASP.NET / generic host
Host
.CreateDefaultBuilder( args )
.AddConfigurationPlaceholders( new InMemoryPlaceholderResolver( new Dictionary<String, String?>
{
{ "FQDN", fullDomainName }
} ) )
ConfigurationBuilder / console application
var configuration = new ConfigurationBuilder()
.AddJsonFile( "appsettings.json" )
....
.AddConfigurationPlaceholders( new List<IPlaceholderResolver>
{
new InMemoryPlaceholderResolver( new Dictionary<String, String?>
{
{
"ApplicationName", Assembly.GetExecutingAssembly().GetName().Name
}
}
} ),
new EnvironmentVariableResolver()
} )
.Build();
Recursive placeholders
You can reference values containing placeholders from placeholders...
{
"Lookup": {
"SinksNs": "Serilog.Sinks",
"DataDir": "X:/Temp/",
"LogDir": "${Lookup:DataDir}logs/",
"DbDir": "${Lookup:DataDir}db/"
},
"Serilog": {
"Using": [ "${Lookup:SinksNs}.Console", "${Lookup:SinksNs}.File" ],
"MinimumLevel": "Debug",
"WriteTo": [
{ "Name": "Console" },
{
"Name": "File",
"Args": { "path": "${Lookup:LogDir}${ApplicationName}/${ApplicationName}-${ApplicationVersion}.log" }
}
]
},
"Test": "Today is the ${Today} (${Day}) an it is ${Time} ${NoValueDefinedForThisOne}",
"LocalDb": "${Lookup:DbDir}store.db"
}
In this example we can see several placeholders referencing values containing other placeholders.
E.g. ${Lookup:DbDir}
will be resolved with the value ${Lookup:DataDir}db/
from Lookup:DbDir
(using ConfigurationPlaceholderResolver
). ${Lookup:DataDir}
is another placeholder which will be replaced with the value of Lookup:DataDir
⇒ X:/Temp/
.
You can combine values from multiple IPlaceholderResolver
with multiple configuration sources.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net8.0
- Azure.Identity (>= 1.13.1)
- Microsoft.Extensions.Configuration (>= 8.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 8.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
2.0.1 | 145 | 11/9/2024 |
2.0.1-preview | 41 | 11/9/2024 |
2.0.0 | 2,478 | 1/17/2024 |
2.0.0-preview | 82 | 1/17/2024 |
1.0.4 | 15,906 | 12/10/2022 |
1.0.4-preview-nugetMetaData | 110 | 12/10/2022 |
1.0.4-preview-net8 | 75 | 1/17/2024 |
1.0.4-preview-multiTarget | 115 | 12/10/2022 |
1.0.3 | 302 | 12/10/2022 |
1.0.3-preview-PRtest | 122 | 12/10/2022 |
1.0.2 | 302 | 12/10/2022 |
1.0.2-preview-PRtest | 123 | 12/10/2022 |
1.0.2-preview-doc | 132 | 12/9/2022 |
1.0.1 | 303 | 12/9/2022 |
1.0.1-preview-f1 | 130 | 12/9/2022 |
1.0.1-preview-doc | 132 | 12/9/2022 |
1.0.0-preview-f1 | 126 | 12/9/2022 |