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

Configuration binding ignores ErrorOnUnknownConfiguration and throws #98231

Open
avendel opened this issue Feb 9, 2024 · 7 comments
Open

Configuration binding ignores ErrorOnUnknownConfiguration and throws #98231

avendel opened this issue Feb 9, 2024 · 7 comments

Comments

@avendel
Copy link

avendel commented Feb 9, 2024

Description

According to a breaking change in .NET 8, configuration binding should throw an InvalidOperationException if the value in the configuration can't be converted to the type of value in the model.

To avoid this behavior, the documentation mentions that you can avoid this by setting BinderOptions.ErrorOnUnknownConfiguration to false.

This does not work, though, and an exception is thrown when the configuration value can't be converted to the type in the model.

Reproduction Steps

dotnet new console
dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.Binder
using Microsoft.Extensions.Configuration;

var builder = new ConfigurationBuilder();
builder.AddInMemoryCollection([
    // Empty string, can't be converted to integer.
    KeyValuePair.Create<string, string?>("IntegerValue", "")
]);
var configuration = builder.Build();
// This throws an InvalidOperationException.
var options = configuration.Get<TestOptions>(o => o.ErrorOnUnknownConfiguration = false);

// Expect default value of 11
Console.WriteLine(options?.IntegerValue);

public class TestOptions {
    public int IntegerValue { get; set; } = 11;
}

Expected behavior

No exception thrown, according to description in https://learn.microsoft.com/en-us/dotnet/core/compatibility/extensions/8.0/configurationbinder-exceptions#recommended-action.

Actual behavior

Exception thrown when trying to bind configuration to options instance. This will also occur when using .Configure<TOptions> and using IOptions<TOptions> via the DI framework.

Unhandled exception. System.InvalidOperationException: Failed to convert configuration value at 'IntegerValue' to type 'System.Int32'.
 ---> System.ArgumentException:  is not a valid value for Int32. (Parameter 'value')
 ---> System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.ComponentModel.BaseNumberConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
   --- End of inner exception stack trace ---
   at System.ComponentModel.BaseNumberConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
   at Microsoft.Extensions.Configuration.ConfigurationBinder.TryConvertValue(Type type, String value, String path, Object& result, Exception& error)
   --- End of inner exception stack trace ---
   at Microsoft.Extensions.Configuration.ConfigurationBinder.BindInstance(Type type, BindingPoint bindingPoint, IConfiguration config, BinderOptions options, Boolean isParentCollection)
   at Microsoft.Extensions.Configuration.ConfigurationBinder.BindProperty(PropertyInfo property, Object instance, IConfiguration config, BinderOptions options)
   at Microsoft.Extensions.Configuration.ConfigurationBinder.BindProperties(Object instance, IConfiguration configuration, BinderOptions options)
   at Microsoft.Extensions.Configuration.ConfigurationBinder.BindInstance(Type type, BindingPoint bindingPoint, IConfiguration config, BinderOptions options, Boolean isParentCollection)
   at Microsoft.Extensions.Configuration.ConfigurationBinder.Get(IConfiguration configuration, Type type, Action`1 configureOptions)
   at Microsoft.Extensions.Configuration.ConfigurationBinder.Get[T](IConfiguration configuration, Action`1 configureOptions)

Regression?

I haven't tested, but I assume so, since this was the reason for the breaking change.

Known Workarounds

No response

Configuration

.NET 8.0.0
Windows 11
x64

Other information

Related issue: #73915

@ghost ghost added the untriaged New issue has not been triaged by the area owner label Feb 9, 2024
@ghost
Copy link

ghost commented Feb 9, 2024

Tagging subscribers to this area: @dotnet/area-extensions-configuration
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

According to a breaking change in .NET 8, configuration binding should throw an InvalidOperationException if the value in the configuration can't be converted to the type of value in the model.

To avoid this behavior, the documentation mentions that you can avoid this by setting BinderOptions.ErrorOnUnknownConfiguration to false.

This does not work, though, and an exception is thrown when the configuration value can't be converted to the type in the model.

Reproduction Steps

dotnet new console
dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.Binder
using Microsoft.Extensions.Configuration;

var builder = new ConfigurationBuilder();
builder.AddInMemoryCollection([
    // Empty string, can't be converted to integer.
    KeyValuePair.Create<string, string?>("IntegerValue", "")
]);
var configuration = builder.Build();
// This throws an InvalidOperationException.
var options = configuration.Get<TestOptions>(o => o.ErrorOnUnknownConfiguration = false);

// Expect default value of 11
Console.WriteLine(options?.IntegerValue);

public class TestOptions {
    public int IntegerValue { get; set; } = 11;
}

Expected behavior

No exception thrown, according to description in https://learn.microsoft.com/en-us/dotnet/core/compatibility/extensions/8.0/configurationbinder-exceptions#recommended-action.

Actual behavior

Exception thrown when trying to bind configuration to options instance. This will also occur when using .Configure<TOptions> and using IOptions<TOptions> via the DI framework.

Unhandled exception. System.InvalidOperationException: Failed to convert configuration value at 'IntegerValue' to type 'System.Int32'.
 ---> System.ArgumentException:  is not a valid value for Int32. (Parameter 'value')
 ---> System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.ComponentModel.BaseNumberConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
   --- End of inner exception stack trace ---
   at System.ComponentModel.BaseNumberConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
   at Microsoft.Extensions.Configuration.ConfigurationBinder.TryConvertValue(Type type, String value, String path, Object& result, Exception& error)
   --- End of inner exception stack trace ---
   at Microsoft.Extensions.Configuration.ConfigurationBinder.BindInstance(Type type, BindingPoint bindingPoint, IConfiguration config, BinderOptions options, Boolean isParentCollection)
   at Microsoft.Extensions.Configuration.ConfigurationBinder.BindProperty(PropertyInfo property, Object instance, IConfiguration config, BinderOptions options)
   at Microsoft.Extensions.Configuration.ConfigurationBinder.BindProperties(Object instance, IConfiguration configuration, BinderOptions options)
   at Microsoft.Extensions.Configuration.ConfigurationBinder.BindInstance(Type type, BindingPoint bindingPoint, IConfiguration config, BinderOptions options, Boolean isParentCollection)
   at Microsoft.Extensions.Configuration.ConfigurationBinder.Get(IConfiguration configuration, Type type, Action`1 configureOptions)
   at Microsoft.Extensions.Configuration.ConfigurationBinder.Get[T](IConfiguration configuration, Action`1 configureOptions)

Regression?

I haven't tested, but I assume so, since this was the reason for the breaking change.

Known Workarounds

No response

Configuration

.NET 8.0.0
Windows 11
x64

Other information

Related issue: #73915

Author: avendel
Assignees: -
Labels:

area-Extensions-Configuration

Milestone: -

@tarekgh
Copy link
Member

tarekgh commented Feb 9, 2024

Regression?
I haven't tested, but I assume so, since this was the reason for the breaking change.

To clarify, this is not a regression. The current behavior is same as pervious .NET versions behavior.

It looks we missed the case that is using type converters. we need to handle the cases when calling TryConvertValue to check ErrorOnUnknownConfiguration before throwing.


@tarekgh tarekgh added this to the Future milestone Feb 9, 2024
@ghost ghost removed the untriaged New issue has not been triaged by the area owner label Feb 9, 2024
@galakt
Copy link
Contributor

galakt commented Apr 16, 2024

@tarekgh Hello, any update on this item? Do you have timeline for this fix?

@tarekgh
Copy link
Member

tarekgh commented Apr 16, 2024

@galakt We currently have higher-priority tasks at hand. If you're interested in submitting a pull request for those, we welcome your contribution.

@krmayankk
Copy link

We are also running into this issue and can potentially help fix it with some guidance, if no one else is working on this

@vivinjoy
Copy link

vivinjoy commented Jun 24, 2024

Can we also get this breaking change for .Net 8 documentation changed? It's currently the same behavior as in .Net 6, where type mismatch errors during configuration binding always throws an error by default.

@tarekgh
Copy link
Member

tarekgh commented Jun 24, 2024

@krmayankk feel free to submit a PR if you are interested. My comment #98231 (comment) explain what need to be done I guess.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants
@vivinjoy @galakt @tarekgh @avendel @krmayankk and others