|
| 1 | +--- |
| 2 | +title: "Breaking change: Empty keys added to dictionary by configuration binder" |
| 3 | +description: Learn about the .NET 8 breaking change in .NET extensions where empty keys are now added to dictionary types by the configuration binder. |
| 4 | +ms.date: 07/27/2023 |
| 5 | +--- |
| 6 | +# Empty keys added to dictionary by configuration binder |
| 7 | + |
| 8 | +In previous versions, when configuration was bound to a dictionary type, any keys without corresponding values in the configuration were skipped and weren't added to the dictionary. The behavior has changed such that those keys are longer skipped but instead automatically created with their default values. This change ensures that all keys listed in the configuration will be present within the dictionary. |
| 9 | + |
| 10 | +## Version introduced |
| 11 | + |
| 12 | +.NET 8 Preview 5 |
| 13 | + |
| 14 | +## Previous behavior |
| 15 | + |
| 16 | +Previously, empty keys in the configuration were skipped when bound to a dictionary type. Consider the following configuration string and binding code. |
| 17 | + |
| 18 | +```csharp |
| 19 | +var json = @"{ |
| 20 | + ""Queues"": { |
| 21 | + ""q1"": { |
| 22 | + ""V"": 1 |
| 23 | + }, |
| 24 | + ""q2"": { |
| 25 | + ""V"": 2 |
| 26 | + }, |
| 27 | + ""q3"": { |
| 28 | + } |
| 29 | + } |
| 30 | +}"; |
| 31 | +``` |
| 32 | + |
| 33 | +```csharp |
| 34 | +public class Q |
| 35 | +{ |
| 36 | + public Dictionary<string, QueueValue> Queues { get; set; } = new(); |
| 37 | +} |
| 38 | + |
| 39 | +public class QueueValue |
| 40 | +{ |
| 41 | + public int V { get; set; } |
| 42 | +} |
| 43 | + |
| 44 | +var configuration = new ConfigurationBuilder() |
| 45 | + .AddJsonStream(StringToStream(json)) |
| 46 | + .Build(); |
| 47 | + |
| 48 | +Q options = new Q(); |
| 49 | +configuration.Bind(options); |
| 50 | +foreach (var kvp in options.Queues) |
| 51 | +{ |
| 52 | + Console.WriteLine($"{kvp.Key}: {kvp.Value.V}"); |
| 53 | +} |
| 54 | +``` |
| 55 | + |
| 56 | +Previously, you'd see the following output (notice that key `q3` is missing): |
| 57 | + |
| 58 | +```output |
| 59 | +q1: 1 |
| 60 | +q2: 2 |
| 61 | +``` |
| 62 | + |
| 63 | +## New behavior |
| 64 | + |
| 65 | +Starting in .NET 8, empty configuration keys are added to the dictionary with their default value during configuration binding. |
| 66 | + |
| 67 | +Consider the code from the [previous behavior](#previous-behavior) section, which now outputs the following text showing that `q3` was added to the dictionary with its default value: |
| 68 | + |
| 69 | +```output |
| 70 | +q1: 1 |
| 71 | +q2: 2 |
| 72 | +q3: 0 |
| 73 | +``` |
| 74 | + |
| 75 | +## Type of breaking change |
| 76 | + |
| 77 | +This change is a [behavioral change](../../categories.md#behavioral-change). |
| 78 | + |
| 79 | +## Reason for change |
| 80 | + |
| 81 | +This user-requested change ensures that all keys listed in the configuration are present within the dictionary. Having all keys present streamlines the process and avoids potential issues with missing keys. |
| 82 | + |
| 83 | +## Recommended action |
| 84 | + |
| 85 | +Verify and adapt your application logic to accommodate the presence of the newly created dictionary entries with empty values. If the new behavior is undesirable, remove empty-value entries from the configuration. By eliminating these entries, no dictionary entries with empty values will be added during the binding process. |
| 86 | + |
| 87 | +## Affected APIs |
| 88 | + |
| 89 | +- <xref:Microsoft.Extensions.Configuration.ConfigurationBinder?displayProperty=fullName> |
| 90 | +- [IConfigurationRoot extension methods](xref:Microsoft.Extensions.Configuration.IConfigurationRoot#extension-methods) |
| 91 | +- <xref:Microsoft.Extensions.DependencyInjection.OptionsConfigurationServiceCollectionExtensions?displayProperty=fullName> |
0 commit comments