MicrosoftConfigurationBuilders icon indicating copy to clipboard operation
MicrosoftConfigurationBuilders copied to clipboard

AzureAppConfigurationBuilder does not match keys in "Strict" mode

Open rehret opened this issue 1 year ago • 0 comments

AzureAppConfigurationBuilder does not match keys in "Strict" mode

When operating in "Strict" mode, AzureAppConfigurationBuilder does not properly match keys from the config section. However, the keys are properly matched in "Greedy" mode.

Functional impact

When utilizing AzureAppConfigurationBuilder in "Strict" mode and using a key filter and prefix, keys are never matched. That is to say values specified in Azure App Configuration are never returned.

Minimal repro steps

Sample project can be found here: rehret/ConfigBuilders.AzureAppConfig.StrictModeTest. The README at the root contains instructions for setup and execution of the test scenario.

Generally speaking, the reproduction steps are:

  1. Define an Azure App Configuration config builder in the Web.config / App.config for the project.
    • The mode must be "Strict"
    • A key filter and prefix must be used
    • stripPrefix must be "true"
  2. Utilize the defined config builder in any configuration section by adding it to the section's configBuilders="..." attribute.
  3. Attempt to read a key defined in the configuration section whose value should be provided by the Azure App Configuration config builder.
  4. The returned value will be null.

Expected result

When reading configuration backed by an Azure App Configuration config builder in "Strict" mode with a key filter and prefix, it is expected that the value specified in Azure App Configuration with a matching key ("key" here being prefix + key) is returned.

Actual result

In "Strict" mode with a key filter and prefix, rather than returning the value specified in Azure App Configuration, AzureAppConfigurationBuilder returns null.

Further technical details

I believe the following is contributing to this:

  • AzureAppConfigurationBuilder performs greedy initialization in "Strict" mode in order to reduce the number of calls to Azure App Configuration. ^1
  • Greedy intialization calls GetAllValues(string prefix) so that all values can be cached immediately. ^2
  • In AzureAppConfigurationBuilder's GetAllValuesAsync(string prefix), the keys (and values) matching the prefix are retrieved and returned. Note that the prefix is left inact in the KeyValuePair key. ^3
  • The returned keys and values are then stored in _cachedValues with the prefix being removed from the keys. ^4
  • Later, in ProcessConfigurationSection(ConfigurationSection configSection), GetValueInternal(string key) is called when in "Strict" mode in order to retrieve the value from _cachedValues, if it exists there, or to read the value from the configuration source if it does not exist in _cachedValues. ^5
  • The key used for cache lookup in GetValueInternal(string key) is prefix + key. ^6 Since the keys were added to _cachedValues without the prefix, it's a cache miss, so GetValue(string key) is called. ^7
  • In AzureAppConfigurationBuilder's GetValue(string key), if a key filter is in use it simply returns null. ^8 The expectation is that GetValue(string key) is never called for AzureAppConfigurationBuilder because it tries to greedily initialize, even in "Strict" mode, meaning it should already have the keys and values preloaded in _cachedValues. However, since the prefix is inconsistently handled in this particular path, every lookup results in a cache miss, which means a null value is always returned here.

rehret avatar Sep 06 '23 19:09 rehret