Description
Related: dotnet/docs#46890 [Breaking change]: Preserving Null Values in Configuration
In versions before 10.0, Microsoft.Extensions.Configuration would throw an Exception when attempting to parse a null value into a non-nullable value type.
// Exception message from Microsoft.Extensions.Configuration 9.0.17
Failed to convert configuration value at 'TestOption:TheDayOfTheWeek' to type 'System.DayOfWeek'.
Starting in version 10.0, null will be silently coerced into the default value for that property.
Reproduction Steps
Using the default settings for a file-based app will produce different behavior for versions of Microsoft.Extensions.Hosting before 10.0 because PublishAot is enabled by default.
This might a completely separate bug, but the behavior of Microsoft.Extensions.Configuration@9.0.17 depends on where AOT is enable or not. When enabled, it behaves like Microsoft.Extensions.Configuration@10.09. I'm not familiar with AOT, so I'm not sure if minor differences in behavior are acceptable or not.
// #:package Microsoft.Extensions.Hosting@9.0.17
#:package Microsoft.Extensions.Hosting@10.0.9
#:property TargetFramework=net10.0
#:property PublishAot=false
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using System.Text;
string jsonString1 =
$$"""
{
"TestOption": {
"TheDayOfTheWeek": null
}
}
""";
TestJson(jsonString1);
static void TestJson(string jsonString)
{
var builder = Host.CreateEmptyApplicationBuilder(null);
builder.Configuration
.AddJsonStream(new MemoryStream(Encoding.UTF8.GetBytes(jsonString)));
builder.Services
.AddOptions<TestOption>()
.BindConfiguration("TestOption");
var host = builder.Build();
try
{
var options = host.Services.GetRequiredService<IOptions<TestOption>>().Value;
Console.WriteLine(options.TheDayOfTheWeek);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
public record TestOption
{
public required DayOfWeek TheDayOfTheWeek { get; init; }
}
Expected behavior
InvalidOperationException with the message
Failed to convert configuration value at 'TestOption:TheDayOfTheWeek' to type 'System.DayOfWeek'.
Actual behavior
No InvalidOperationException is thrown and its message is written to the console.
Regression?
Yes, this was changed with .NET preview 7 according to dotnet/docs#46890.
Known Workarounds
No response
Configuration
Windows 11 Pro 25H2 (x64)
Dotnet 10.0.202
AOT Disabled (this makes a difference)
Other information
I personally prefer being as explicit as possible and differentiating between null and 0, but I don't think I can come up with a realistic use case where the distinction matters. The lack of any mention of non-nullable value types in dotnet/docs#46890 leads me to believe these changes were unintentional. It may be more appropriate to just update the documentation.
Description
Related: dotnet/docs#46890 [Breaking change]: Preserving Null Values in Configuration
In versions before 10.0, Microsoft.Extensions.Configuration would throw an Exception when attempting to parse a null value into a non-nullable value type.
Starting in version 10.0, null will be silently coerced into the default value for that property.
Reproduction Steps
Using the default settings for a file-based app will produce different behavior for versions of Microsoft.Extensions.Hosting before 10.0 because PublishAot is enabled by default.
This might a completely separate bug, but the behavior of Microsoft.Extensions.Configuration@9.0.17 depends on where AOT is enable or not. When enabled, it behaves like Microsoft.Extensions.Configuration@10.09. I'm not familiar with AOT, so I'm not sure if minor differences in behavior are acceptable or not.
Expected behavior
InvalidOperationException with the message
Actual behavior
No InvalidOperationException is thrown and its message is written to the console.
Regression?
Yes, this was changed with .NET preview 7 according to dotnet/docs#46890.
Known Workarounds
No response
Configuration
Windows 11 Pro 25H2 (x64)
Dotnet 10.0.202
AOT Disabled (this makes a difference)
Other information
I personally prefer being as explicit as possible and differentiating between null and 0, but I don't think I can come up with a realistic use case where the distinction matters. The lack of any mention of non-nullable value types in dotnet/docs#46890 leads me to believe these changes were unintentional. It may be more appropriate to just update the documentation.