diff --git a/docs/core/compatibility/8.0.md b/docs/core/compatibility/8.0.md index a6fe33bc08702..61f1d47a9f262 100644 --- a/docs/core/compatibility/8.0.md +++ b/docs/core/compatibility/8.0.md @@ -80,6 +80,7 @@ See [Breaking changes in EF Core 8](/ef/core/what-is-new/ef-core-8.0/breaking-ch |-----------------------------------------------------------------------------------------------------------------------------------|-------------------| | [ActivatorUtilities.CreateInstance behaves consistently](extensions/8.0/activatorutilities-createinstance-behavior.md) | Behavioral change | | [ActivatorUtilities.CreateInstance requires non-null provider](extensions/8.0/activatorutilities-createinstance-null-provider.md) | Behavioral change | +| [ConfigurationBinder silently skips invalid array elements](extensions/8.0/configurationbinder-skips-failed-array-elements.md) | Behavioral change | | [ConfigurationBinder throws for mismatched value](extensions/8.0/configurationbinder-exceptions.md) | Behavioral change | | [ConfigurationManager package no longer references System.Security.Permissions](extensions/8.0/configurationmanager-package.md) | Source incompatible | | [DirectoryServices package no longer references System.Security.Permissions](extensions/8.0/directoryservices-package.md) | Source incompatible | diff --git a/docs/core/compatibility/extensions/8.0/configurationbinder-exceptions.md b/docs/core/compatibility/extensions/8.0/configurationbinder-exceptions.md index 2b329666327a4..82e56fe6f191c 100644 --- a/docs/core/compatibility/extensions/8.0/configurationbinder-exceptions.md +++ b/docs/core/compatibility/extensions/8.0/configurationbinder-exceptions.md @@ -71,3 +71,7 @@ Alternatively, set - - + +## See also + +- [ConfigurationBinder silently skips invalid array elements](configurationbinder-skips-failed-array-elements.md) diff --git a/docs/core/compatibility/extensions/8.0/configurationbinder-skips-failed-array-elements.md b/docs/core/compatibility/extensions/8.0/configurationbinder-skips-failed-array-elements.md new file mode 100644 index 0000000000000..6a1ed93969de2 --- /dev/null +++ b/docs/core/compatibility/extensions/8.0/configurationbinder-skips-failed-array-elements.md @@ -0,0 +1,79 @@ +--- +title: "Breaking change: ConfigurationBinder silently skips invalid array elements" +description: "Learn about the breaking change in .NET 8 where ConfigurationBinder silently skips array or list elements that fail type conversion instead of preserving null placeholders." +ms.date: 03/11/2026 +ai-usage: ai-assisted +--- + +# ConfigurationBinder silently skips invalid array elements + +Starting in .NET 8, silently skips array and list elements whose values can't be converted to the target type. Previously, failed elements were preserved as `null` placeholders, and the resulting collection retained the same length as the number of elements in the configuration source. + +## Version introduced + +.NET 8 + +## Previous behavior + +Previously, when binding an array or list property via or , if an element's value couldn't be converted to the target type, that element was preserved as a `null` placeholder in the result. The collection length matched the number of elements in the configuration. + +```csharp +// Configuration source, for example, appsettings.json: +// "Items": [ +// { "Name": "A", "Interval": 10 }, +// { "Name": "B", "Interval": "a" } <-- invalid int +// ] + +var settings = configuration.GetSection("Items").Get(); + +// .NET 6/7 result: +// settings.Length == 2 +// settings[0] = { Name = "A", Interval = 10 } +// settings[1] = null (conversion failed, placeholder preserved) +``` + +## New behavior + +Starting in .NET 8, elements that fail type conversion are silently skipped. The resulting collection contains only successfully bound elements and has a shorter length than the number of entries in the configuration source. + +```csharp +var settings = configuration.GetSection("Items").Get(); + +// .NET 8+ result: +// settings.Length == 1 +// settings[0] = { Name = "A", Interval = 10 } +``` + +## Type of breaking change + +This change is a [behavioral change](../../categories.md#behavioral-change). + +## Reason for change + +The internal implementation of was refactored in .NET 8. Instead of pre-allocating the target array and binding elements in-place (which left `null` on conversion failure), the binder now collects only successfully bound elements into a temporary list before materializing the final array. + +The previous behavior was also problematic for value types such as `int[]`. For an invalid configuration value, the binder would store `0`, which was indistinguishable from a legitimate value of `0`. The new behavior avoids this ambiguity. + +## Recommended action + +- **Enable during development** to surface invalid configuration values immediately rather than silently dropping elements: + + ```csharp + var settings = configuration.GetSection("Items").Get(options => + options.ErrorOnUnknownConfiguration = true); + ``` + + Starting in .NET 8, this option also causes to throw an when a value can't be converted to the target type. For more information, see [ConfigurationBinder throws for mismatched value](configurationbinder-exceptions.md). + +- **Fix invalid configuration values.** Ensure all values in your configuration source match the expected types for the bound model. + +- **Validate collection lengths** after binding if your code depends on the number of elements matching the configuration source. + +- **Use string properties with manual parsing** if you need to gracefully handle unconvertible values and preserve all array entries. + +## Affected APIs + +- +- +- +- diff --git a/docs/core/compatibility/toc.yml b/docs/core/compatibility/toc.yml index 060aa02d24c20..748675af35f84 100644 --- a/docs/core/compatibility/toc.yml +++ b/docs/core/compatibility/toc.yml @@ -460,6 +460,8 @@ items: href: extensions/8.0/activatorutilities-createinstance-behavior.md - name: ActivatorUtilities.CreateInstance requires non-null provider href: extensions/8.0/activatorutilities-createinstance-null-provider.md + - name: ConfigurationBinder silently skips invalid array elements + href: extensions/8.0/configurationbinder-skips-failed-array-elements.md - name: ConfigurationBinder throws for mismatched value href: extensions/8.0/configurationbinder-exceptions.md - name: ConfigurationManager package no longer references System.Security.Permissions