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

Config binding breaking change #36434

Merged
merged 2 commits into from
Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/core/compatibility/8.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,11 @@ If you're migrating an app to .NET 8, the breaking changes listed here might aff
## Extensions

| Title | Type of change | Introduced |
| --------------------------------------------------------------------------------------------------------------------------------- | ----------------- | ---------- |
|-----------------------------------------------------------------------------------------------------------------------------------|-------------------|------------|
| [ActivatorUtilities.CreateInstance behaves consistently](extensions/8.0/activatorutilities-createinstance-behavior.md) | Behavioral change | Preview 1 |
| [ActivatorUtilities.CreateInstance requires non-null provider](extensions/8.0/activatorutilities-createinstance-null-provider.md) | Behavioral change | Preview 1 |
| [ConfigurationBinder throws for mismatched value](extensions/8.0/configurationbinder-exceptions.md) | Behavioral change | Preview 1 |
| [Empty keys added to dictionary by configuration binder](extensions/8.0/dictionary-configuration-binding.md) | Behavioral change | Preview 5 |
| [HostApplicationBuilderSettings.Args respected by HostApplicationBuilder ctor](extensions/8.0/hostapplicationbuilder-ctor.md) | Behavioral change | Preview 2 |

## Globalization
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
title: "Breaking change: Empty keys added to dictionary by configuration binder"
description: Learn about the .NET 8 breaking change in .NET extensions where empty keys are now added to dictionary types by the configuration binder.
ms.date: 07/27/2023
---
# Empty keys added to dictionary by configuration binder

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.

## Version introduced

.NET 8 Preview 5

## Previous behavior

Previously, empty keys in the configuration were skipped when bound to a dictionary type. Consider the following configuration string and binding code.

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

```csharp
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}");
}
```

Previously, you'd see the following output (notice that key `q3` is missing):

```output
q1: 1
q2: 2
```

## New behavior

Starting in .NET 8, empty configuration keys are added to the dictionary with their default value during configuration binding.

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:

```output
q1: 1
q2: 2
q3: 0
```

## Type of breaking change

This change is a [behavioral change](../../categories.md#behavioral-change).

## Reason for change

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.

## Recommended action

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.

## Affected APIs

- <xref:Microsoft.Extensions.Configuration.ConfigurationBinder?displayProperty=fullName>
- [IConfigurationRoot extension methods](xref:Microsoft.Extensions.Configuration.IConfigurationRoot#extension-methods)
- <xref:Microsoft.Extensions.DependencyInjection.OptionsConfigurationServiceCollectionExtensions?displayProperty=fullName>
4 changes: 4 additions & 0 deletions docs/core/compatibility/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ items:
href: extensions/8.0/activatorutilities-createinstance-null-provider.md
- name: ConfigurationBinder throws for mismatched value
href: extensions/8.0/configurationbinder-exceptions.md
- name: Empty keys added to dictionary by configuration binder
href: extensions/8.0/dictionary-configuration-binding.md
- name: HostApplicationBuilderSettings.Args respected by constructor
href: extensions/8.0/hostapplicationbuilder-ctor.md
- name: Globalization
Expand Down Expand Up @@ -1278,6 +1280,8 @@ items:
href: extensions/8.0/activatorutilities-createinstance-null-provider.md
- name: ConfigurationBinder throws for mismatched value
href: extensions/8.0/configurationbinder-exceptions.md
- name: Empty keys added to dictionary by configuration binder
href: extensions/8.0/dictionary-configuration-binding.md
- name: HostApplicationBuilderSettings.Args respected by constructor
href: extensions/8.0/hostapplicationbuilder-ctor.md
- name: .NET 7
Expand Down
Loading