Overriding appsettings.json section with environment variable
Given a configuration section called
Tenants
, I'd like to override it with a whole JSON structure via an environment variable.
Given I want this
I'm doing
I'm trying to bind it against an object with the options pattern:
And the classes look like:
When I run the ASP.NET Core app, the ByCode
dictionary is empty. But if I just paste the JSON section in appsettings.json, it's correctly populated.
For the record, I can see the whole structure if I just log builder.Configuration.GetSection(TenantsOptions.SectionName).Value;
, but for some reason, I guess it's only interpreted as a string, and not correctly deserialized and bound to TenantOptions
?
So how do you actually override a whole section with a JSON value through an environment variable?16 Replies
I don't see how environment variables apply here
How's that?
I mean I don't see where environment variables are related to your question
Is it that you load appsettings based on the environment?
I suppose you should first check if the resulting configuration from
builder.Configuration.GetSection(TenantsOptions.SectionName)
returns the data you expectI'm setting an env variable externally before running the app, like I mentioned:
export Tenants='{"ByCode": {"11": {"Name": "acme"}, "42": {"Name": "silver"}}}'
You can also try to use
GetRequiredSection
It does return the data I want, it's just that it doesn't bind to the options object.
Even the documentation on this seems to only mention cases where fields in a JSON object are set independently, rather than setting the whole object via a JSON string.
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-9.0#evcp
Configuration in ASP.NET Core
Learn how to use the Configuration API to configure AppSettings in an ASP.NET Core app.
Like instead of doing
export Position='{ "Title": "Environment_Editor", "Name": "Environment_Rick" }'
I don't think what you want is supported. My understanding is IConfiguration takes an environment variable as representing a single atom of configuration, not as something that can potentially represent an entire configuration section. If you set the env var to a JSON string, then IConfiguration will consider it as just a
string
.
I think the 'right' way to do this would be to set up multiple environment variables to override each property of the structure.
e.g. export TENANTS__ByCode = ["foo", "bar"]
you would have to specify multiple
but limitations are that it will get merged, by default with env overriding json, args overriding env
I really feared it wouldn't be supported. Doing
export Tenants__ByCode__11__Name=acme
for the huge actual structure I'm dealing with is really crazy.
Maybe it can be suggested as a potential improvement.you can add more json files if you want, add them as optional
Yeah, I feel like this is a bit of an x/y problem. why do you want to override a big json object with environment variables?
It's a Kubernetes secret injected into the environment.
It's not such a novel idea. Other frameworks support this, like Spring. You can override the whole application config with a JSON-inline env variable
SPRING_APPLICATION_JSON
.
Or just subkeys.you could handle it in code by reading that envvar coming in to a dictionary and adding an InMemoryCollection that would override any existing. not possible to delete keys though, it would be merged
You can certainly write your own ICOnfiguratioSource and Provider.
BUt if this is K8s, it would be better to just use KubernetesConfigurationProvider.