Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Breaking change]: Stop skipping configuration binding a dictionary with a key that has empty value #36431

Closed
1 of 3 tasks
tarekgh opened this issue Jul 27, 2023 · 1 comment · Fixed by #36434
Closed
1 of 3 tasks
Assignees
Labels
breaking-change Indicates a .NET Core breaking change doc-idea Indicates issues that are suggestions for new topics [org][type][category] Pri1 High priority, do before Pri2 and Pri3 📌 seQUESTered Identifies that an issue has been imported into Quest.

Comments

@tarekgh
Copy link
Member

tarekgh commented Jul 27, 2023

Description

In previous versions, when binding configuration to a dictionary type, any keys listed in the configuration without corresponding values would be skipped, resulting in their non-creation within the dictionary. However, a recent breaking change alters this behavior, whereby such keys will no longer be skipped but instead will be automatically created with their default values. This change ensures that all keys listed in the configuration will be present within the dictionary, streamlining the process and avoiding potential issues with missing keys. Developers should be aware of this update and adjust their code accordingly to accommodate the new behavior.

Version

.NET 8 Preview 5

Previous behavior

Consider the following example:

Configuration

var json = @"{
    ""Queues"": {
        ""q1"": {
            ""V"": 1
        },
        ""q2"": {
            ""V"": 2
        },
        ""q3"": {
        }
    }
}";

Code

public class Q
{
    public Dictionary<string, QueueValue> Queues { get; set; } = new();
}

public class QueueValue
{
    public int V { get; set; }
}

var configuration = new ConfigurationBuilder()
    .AddJsonStream(StringToStream(json))
    .Build();

Q options = new Q();
configuration.Bind(options);
foreach (var kvp in options.Queues)
{
    Console.WriteLine($"{kvp.Key}: {kvp.Value.V}");
}

Output

q1: 1
q2: 2

Please take note that the third key, q3, is currently being skipped, resulting in no corresponding dictionary entry being created for it.

New behavior

With the new behavior, the resulting output will now include the q3 key, which was previously skipped. This key will be created and initialized with the default value within the generated dictionary. This change ensures that all listed keys are accounted for, eliminating any potential omissions, and promoting consistency in the dictionary structure.

q1: 1
q2: 2
q3: 0

Type of breaking change

  • Binary incompatible: Existing binaries may encounter a breaking change in behavior, such as failure to load or execute, and if so, require recompilation.
  • Source incompatible: When recompiled using the new SDK or component or to target the new runtime, existing source code may require source changes to compile successfully.
  • Behavioral change: Existing binaries may behave differently at run time.

Reason for change

This change ensures that all keys listed in the configuration will be present within the dictionary, streamlining the process and avoiding potential issues with missing keys. Developers should be aware of this update and adjust their code accordingly to accommodate the new behavior. The users request this new behavior. dotnet/runtime#66229

Recommended action

Users should be aware of the new behavior, which involves the automatic population of dictionary entries with empty values listed in the configuration during the binding process. This change necessitates that users verify and adapt their application logic to accommodate the presence of these newly created entries. If the new behavior is undesirable, the workaround involves removing the empty value entries from the configuration. By eliminating these entries, users can revert to the previous behavior and avoid automatic population of dictionary entries with empty values during the binding process. This allows users to maintain the desired configuration structure according to their specific needs and preferences.

Feature area

Extensions

Affected APIs

ConfigurationBinder
IConfigurationRoot extension methods
OptionsConfigurationServiceCollectionExtensions


Associated WorkItem - 143185

@tarekgh tarekgh added doc-idea Indicates issues that are suggestions for new topics [org][type][category] breaking-change Indicates a .NET Core breaking change Pri1 High priority, do before Pri2 and Pri3 labels Jul 27, 2023
@dotnet-bot dotnet-bot added the ⌚ Not Triaged Not triaged label Jul 27, 2023
@gewarren gewarren removed the ⌚ Not Triaged Not triaged label Jul 27, 2023
@ghost ghost added the in-pr This issue will be closed (fixed) by an active pull request. label Jul 28, 2023
@gewarren gewarren added the 🗺️ reQUEST Triggers an issue to be imported into Quest. label Jul 28, 2023
@github-actions github-actions bot added 📌 seQUESTered Identifies that an issue has been imported into Quest. and removed 🗺️ reQUEST Triggers an issue to be imported into Quest. labels Jul 28, 2023
@ghost ghost removed the in-pr This issue will be closed (fixed) by an active pull request. label Jul 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking-change Indicates a .NET Core breaking change doc-idea Indicates issues that are suggestions for new topics [org][type][category] Pri1 High priority, do before Pri2 and Pri3 📌 seQUESTered Identifies that an issue has been imported into Quest.
Projects
No open projects
Status: Done
Development

Successfully merging a pull request may close this issue.

3 participants