Binding of empty string is inconsistent between reflection and source generator configuration binders
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Description
The following tests fail for the source generated configuration binder, but succeed for the reflection binder, showing inconsistencies between the two binders. I think these should be fixed. It's likely that some fixes will require changing the source generator, and others changing the reflection binder. (In other words, one of these tests succeeding doesn't necessarily mean it's the correct behavior.)
```c#
[Fact]
public void GetValue_EmptyStringForString_ReturnsEmptyString()
{
IConfiguration config = TestHelpers.GetConfigurationFromJsonString("""{ "Value": "" }""");
Assert.Equal(string.Empty, config.GetValue("Value"));
}
[Fact]
public void GetValue_EmptyStringForInt32_Throws()
{
IConfiguration config = TestHelpers.GetConfigurationFromJsonString("""{ "Value": "" }""");
Assert.Throws(() => config.GetValue("Value"));
}
[Fact]
public void GetValue_EmptyStringForByteArray_ReturnsEmptyArray()
{
IConfiguration config = TestHelpers.GetConfigurationFromJsonString("""{ "Value": "" }""");
Assert.Empty(Assert.IsType(config.GetValue("Value")));
}
[Fact]
public void Get_EmptyStringForNullableInt32_ReturnsNull()
{
IConfiguration config = TestHelpers.GetConfigurationFromJsonString("""{ "Value": "" }""");
Assert.Null(config.GetSection("Value").Get());
}
[Fact]
public void Get_EmptyStringForInt32_ThrowsConversionException()
{
IConfiguration config = TestHelpers.GetConfigurationFromJsonString("""{ "Value": "" }""");
Assert.Throws(() => config.GetSection("Value").Get());
}
[Fact]
public void Get_EmptyStringArrayElementWithErrorOnUnknownConfiguration_Throws()
{
IConfiguration config = TestHelpers.GetConfigurationFromJsonString("""{ "Values": [ "" ] }""");
Assert.Throws(
() => config.GetSection("Values").Get(o => o.ErrorOnUnknownConfiguration = true));
}
[Fact]
public void Get_EmptyStringDictionaryValueWithErrorOnUnknownConfiguration_Throws()
{
IConfiguration config = TestHelpers.GetConfigurationFromJsonString("""{ "Values": { "Key": "" } }""");
Assert.Throws(
() => config.GetSection("Values").Get>(o => o.ErrorOnUnknownConfiguration = true));
}
```
Contributor guide
Research direction
Start by running the listed configuration binder tests with the source-generated and reflection binders, using TestHelpers.GetConfigurationFromJsonString and the GetValue/Get entry points. Compare each empty-string result and determine the intended behavior before changing either implementation. Done means both binders consistently handle strings, numeric values, byte arrays, nullable values, arrays, and dictionary values, with the expected exceptions.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100