Skip to content

Commit 9fa2ecb

Browse files
authored
Fix using right configuration provider order when getting configuration value (#117474)
1 parent 07cf21a commit 9fa2ecb

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3007,5 +3007,36 @@ public void BindArraysWithNullAndOtherValues()
30073007
Assert.Equal([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], instance.ByteArray3);
30083008
#endif
30093009
}
3010+
3011+
[Fact]
3012+
public void TestProvidersOrder()
3013+
{
3014+
string jsonConfig1 = @"
3015+
{
3016+
""SimplePoco"": {
3017+
""A"": ""Provider1A"",
3018+
""B"": ""Provider1B"",
3019+
},
3020+
}";
3021+
3022+
// Missing B in the second provider should not override the value from the first provider.
3023+
string jsonConfig2 = @"
3024+
{
3025+
""SimplePoco"": {
3026+
""A"": ""Provider2A"",
3027+
},
3028+
}";
3029+
3030+
var configuration = new ConfigurationBuilder()
3031+
.AddJsonStream(new MemoryStream(Encoding.UTF8.GetBytes(jsonConfig1)))
3032+
.AddJsonStream(new MemoryStream(Encoding.UTF8.GetBytes(jsonConfig2)))
3033+
.Build().GetSection("SimplePoco");
3034+
3035+
SimplePoco? result = configuration.Get<SimplePoco>();
3036+
3037+
Assert.NotNull(result);
3038+
Assert.Equal("Provider2A", result.A); // Value should come from the last provider
3039+
Assert.Equal("Provider1B", result.B); // B should not be overridden by the second provider
3040+
}
30103041
}
30113042
}

src/libraries/Microsoft.Extensions.Configuration/src/InternalConfigurationRootExtensions.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,15 @@ internal static IEnumerable<IConfigurationSection> GetChildrenImplementation(thi
4242

4343
internal static bool TryGetConfiguration(this IConfigurationRoot root, string key, out string? value)
4444
{
45-
foreach (IConfigurationProvider provider in root.Providers)
45+
// common cases Providers is IList<IConfigurationProvider> in ConfigurationRoot
46+
IList<IConfigurationProvider> providers = root.Providers is IList<IConfigurationProvider> list
47+
? list
48+
: root.Providers.ToList();
49+
50+
// ensure looping in the reverse order
51+
for (int i = providers.Count - 1; i >= 0; i--)
4652
{
53+
IConfigurationProvider provider = providers[i];
4754
if (provider.TryGet(key, out value))
4855
{
4956
return true;

0 commit comments

Comments
 (0)