0

For the life of me I cannot find much official information on the load order or precedence of configuration file load order.

I have a situation where I am provided configuration via AddAzureKeyVault which is fine, but I also have a local user secrets json setup which contains a connection string that I want to overwrite the key vault provided one.

The example Configuration setup looks like so:

    builder.Configuration
        .AddAzureKeyVault(someKvUri, new DefaultAzureCredential())
        .AddEnvironmentVariables();

#if DEBUG
    builder.Configuration.AddUserSecrets("some-id");
#endif

The hope here is in a Debug build it will allow the developer to overwrite whatever settings they want from the provided ones with whatever is local in the user secrets, be it variables, connection strings etc.

Problem is it doesn't work and there is seemingly no documentation detailing the load order of these 2 things when used together. The KV always takes precedence so its not overwriting the values.

I have put in some other whimsical values in the user secrets and can see them being added to the Configuration object, so I know its being loaded, and if I comment out the AddAzureKeyVault line then I get my user secret values populated, however it feels like the local user secrets should take the maximum precedence here.

I have also tried moving the AddUserSecrets above the key vault registration bit, and setting reloadOnChange to true/false, neither alters behaviour.

So is there a way to have the user secrets overwrite whats provided by the KV? without going into the scenario we cannot use appsettings.Development.json to overwrite stuff it has to be done via some other file/mechanism, and it was agreed user secrets would be the better way to allow individual developers to re-point certain resources to use local ones, i.e sql servers, cosmos dbs, queues etc.

== Edit 1 == As per comments here is some more information: example debug output from loaded configuration example user secrets json

As you can see the user secrets are loaded as the 2nd value is present in the config, however the first value is not present, the only one present for that key is the KV one which is ConnectionStrings--TheKeyName.

So from what I can see here the KV is overwriting the user secret value, and it doesnt matter if I load the KV before or after the secrets. Also just to confirm if I were to remove the KV loading then I correctly see the user secret first value in the configuration.

4
  • 1
    shouldn't really happen judging from the implementation code. Commented Sep 22 at 17:52
  • 1
    If you look at the IConfiguration instance in a debugger, you can see the providers in order: check that. IME the precedence is 100% driven by the order providers are added to the builder (remember you can .Clear() to remove the default included providers). Commented Sep 22 at 19:58
  • Try calling AddUserSecrets before AddAzureKeyVault Commented Sep 23 at 5:12
  • Added example user secrets and configuration debug output to show how value is missing when KV has same property. Commented Sep 23 at 7:28

2 Answers 2

1

As stated here:

The last key loaded wins.

This means in your provided code example, that values from environment variables will overwrite values from the key vault.

But you have to take care for the different rules of each provider about how nested values (like objects with properties) are written and other stuff. E.g. the key vault works with double minus sign as separator, while the provider for environment variables checks for a double underscore and (depending on your other configuration) maybe needs a prefix on every key. Further details about the most common configuration providers can be found here in the documentation.

Sign up to request clarification or add additional context in comments.

1 Comment

Yeah we use the -- to mimic the hierarchical data, so we have the same properties in KV and User Secrets, lets say Something--Foo in KV and Something:Foo in user secrets. We will only see the Something:Foo from KV. As mentioned though if I were to add ImACow:Moo to the user secrets as well, I would see that in the Configuration object, so it is loading them both, just only listing the Something:Foo from the KV, so it does not seem to honour the last key loaded rule here.
0

Ok stand down, it seems like its doing something odd behind the scenes, even without me explicitly adding the AddUserSecrets call it is already adding the secrets file into the configuration sources auto-magically and its already in there before we get to the code that adds the KV etc, so its always going to be there before hand.

I can manually remove the sources and re-add them but it looks like the precedence is correct its just doing unexpected behaviour behind the scenes which is contradicting and causing my explicit load order to be ignored.

Also to make things more confusing it seems I should have been calling AddUserSecrets(typeof(Program).Assembly) not AddUserSecrets("some-id-used-at-some-point")

1 Comment

yeah AddUserSecrets is added by default together with other ones, maybe adding it a second time is a no-op and it retains its position in the order before AddKeyVault which you add last.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.