I have an application running on .NET 5. We have a configuration file which looks like this
{
"Config1" : {
"k1" : "v1",
"k2" : "v2"
...........
},
"Config2" : {
"k3" : "v3",
"k4" : "v4"
}
}
Using a singleton object to load the configuration as
services.Configure<Config1>(
this.Configuration.GetSection(nameof(Config1)));
services.Configure<Config2>(
this.Configuration.GetSection(nameof(Config2)));
And these objects are injected into calling function using constructor.
public claas C1
{
public IOptionsMonitor<Config1>
public C1(IOptionsMonitor<Config2> config2, IOptionsMonitor<Config1> config1)
{
this.config2 = config2;
this.config1 = config1;
}
}
Now we need to add a new configuration in the config file which should override some of the existing configs based on the payload from user.
So Config3 object will look like
"Config3" : {
"userDefinedprop1" : {
"Config2" : {
"k4" : "v4"
}
},
"userDefinedprop2" : {
"Config1" : {
"k1" : "v1"
}
}
}
I want to override some of the existing properties in config1 and config2 based on user input for each incoming request i.e during runtime. How should I approach this without breaking the existing functionality.
First of all, make sure you understand very well the Configuration Provider model used in ASP.NET Core. This Provider model allows you to add additional Providers to the "source of truth" for the application's Configuration, which is what your Options Models are bound to.
Normally you can add static data as an "in memory collection" using an existing provider:
But obviously this will not be updateable nor respond to any changes. ASP.NET Core doesn't have a Provider that does this, so you will need to write your own and add it to the application's Configuration.
In order to send updates to the Provider, we'll need an interface that can be injected into our Controllers:
And then the Provider itself can use the existing
ConfigurationProviderbase class to build off of:a couple notes:
IConfigurationSourceis the interface required to add a Provider to the application. theConfigurationProviderbase class already has aDictionarywe can use to store data in and a "reload token" we can use to trigger update notifications. however we need to override theSet()method to trigger the reload token so consumers will be notified.and finally register your new provider in 2 places. 1 - add it as a Singleton to dependency injection so it can be consumed in Controllers:
2 - add the instance as a Configuration "Source" to the Configuration subsystem:
Now you can inject
IUserConfigurationSourceinto a Controller and update the data when the users change it:and your use of
IOptionsMonitorwill be able to access the updated values:however, note that if you have nested config keys, you'll need to use a colon (":") to list the full path of the config key in order for it to be bound to the Options correctly, so for your example config you might have:
good luck!