Description
Is there an existing issue for this?
- I have searched the existing issues
Describe the bug
I have the following properties in a Model class:
[Column("end_date")]
[Display(Name = nameof(Resources.CommonCaptions.EndingOn), ResourceType = typeof(Resources.CommonCaptions))]
public DateTime? EndDate { get; set; }
public Dictionary<int, WeekTimeIntervals>? WeekIntervals { get; set; }
a WeekTimeIntervals declaration is:
public class TimeInterval
{
public DateTime? From { get; set; }
public DateTime? To { get; set; }
}
public class WeekTimeIntervals
{
public Dictionary<int, TimeInterval>? TimeIntervals { get; set; }
}
When the EndDate value is not provided on the form, the WeekIntervals[0].Value.TimeIntervals is bind as null, even the values for the one of time interval is set.
FormMappingContext includes the following errors:
Model.EndDate
{The value '' is not valid for 'EndDate'.}
Model.WeekIntervals[1].TimeIntervals[2].From
{The value '' is not valid for 'From'.}
Model.WeekIntervals[1].TimeIntervals[2].To
{The value '' is not valid for 'To'.}
Model.WeekIntervals[1].TimeIntervals[0].From
{The value '' is not valid for 'From'.}
Model.WeekIntervals[1].TimeIntervals[0].To
{The value '' is not valid for 'To'.}
Model.WeekIntervals[1].TimeIntervals[0]
{'Model.EndDate' does must start with 'Model.WeekIntervals[1].TimeIntervals[0]'}
Model.WeekIntervals[1].TimeIntervals
{'Model.EndDate' does must start with 'Model.WeekIntervals[1].TimeIntervals'}
Model.WeekIntervals[1]
{'Model.EndDate' does must start with 'Model.WeekIntervals[1]'}
Model.WeekIntervals
{'Model.EndDate' does must start with 'Model.WeekIntervals'}
A few errors above (at the list end) look wierd ('Model.EndDate' does must start with 'Model.WeekIntervals[1].TimeIntervals[0]').
I found a reference of this error message here: FormMappingContext.cs#L139
internal void AttachParentValue(string key, object value)
{
if (_pendingErrors == null)
{
return;
}
for (var i = 0; i < _pendingErrors.Count; i++)
{
var (errorKey, error) = _pendingErrors[i];
if (!errorKey.StartsWith(key, StringComparison.Ordinal))
{
throw new InvalidOperationException($"'{errorKey}' does must start with '{key}'");
}
error.Container = value;
}
_pendingErrors.Clear();
}
I don't understand why this method is called for the "Model.EndDate" key while attaching a value to the "Model.WeekIntervals" dictionary.
If I change the properties order to make WeekIntervals to go before the EndDate property, the issue is not reproduced.
Expected Behavior
Expect WeekIntervals[0].Value.TimeIntervals has been bind to a value sent from a form correct.
Steps To Reproduce
No response
Exceptions (if any)
It is a simple NullReferenceException
.NET Version
8.0.204
Anything else?
No response
Activity
sgarnovsky commentedon Oct 7, 2024
Created a sample app to show the issue.
BlazorFormMappingContextIssue
If empty values are posted form mapping context errors are:
The important issue here that the Container property of the last 2 errors are set to the Example type instance instead of the Person one.
Originally we thought that the issue is only appears when empty values are posted for nullable model properties. But the same issue appears in a case if some invalid value is posted.
It doesn't matter what property type is used: DateTime, int.
So, the problem is related to using a property of a complex type after a property of a simple type.
A Blazor form sample code is:
if the Person property is declared before the TestValue property - issue is not reproduced.
In this case, Form Mapping Context errors are generated as:
It looks like a bug somewhere in the Form Mapping logic.
TomSkidmore commentedon Dec 6, 2024
I'm guessing there's no movement on this one. This is something we're currently encountering. The poorly worded validation messages aside, it looks as though you simply cannot have nullable values in Blazor SSR. InputNumber and InputDate validate incorrectly if your property is a nullable, even if you set the TValue (you get the '' is not valid message)
Really poor to see no movement on this one as optional numeric and date fields are an absolute must for forms
Looks like a similarly reported issue here: #58988
sgarnovsky commentedon Dec 6, 2024
this one is a bit different.
Maybe, the described issue is only a result of the nullable values binding problem.
xxnickles commentedon Dec 10, 2024
I just found this issue after opening a one related to nullable enums. For the issues I have found in this repo, I think the problem is the support of standard forms is just bad in certain areas of asp.net (Blazor and minimal API in my experience). Honestly, I think the documentation should just recommend no having nullable properties and complex objects as properties and collection that are not primitives, which also have poor support in SSR and minimal APIs as far I have been able to play with.
My workaround is not relaying on nullables, but using always defaults + validation, avoid complex properties altogether and bind everything to big POCO objects and go from there by myself. To me, it is very frustrating to find this kind of problems with forms, which is a fundamental web construct since the early days...and one would think a solved issue! Yes, I understand supporting fancy mainstream JSON is quite relevant, but forgetting the fundamentals is kind of a big red flag for a web framework
sgarnovsky commentedon Apr 2, 2025
I've got stuck with this issue on .Net 9 again.
It looks bad as this issue is referenced to "area-mvc" label.
Actually, it is a problem with the Blazor static SSR forms binding.
A workaround is to just place complex type properties before any nullable properties in the main class declarations.
My assumption that this problem is related to the issue of binding empty string values into nullable fields. It ends up into unexpected results for the complex properties declared after an issued nullable property.
So this issue is referenced with this one: 52499
The needed fix is assumed to be applied for .Net 10 preview2. Confirmed it here: https://github.com/dotnet/aspnetcore/blob/v10.0.0-preview.2.25164.1/src/Components/Endpoints/src/FormMapping/Converters/NullableConverter.cs
.Net 9 last release doesn't reference these updates: https://github.com/dotnet/aspnetcore/blob/v9.0.3/src/Components/Endpoints/src/FormMapping/Converters/NullableConverter.cs
sgarnovsky commentedon Apr 2, 2025
Confirmed the original issue looks fixed by an applied improvement discussed here: 52499.
One thing that it is only available starting from the .Net 10 Preview 2 now.
Will plan to close this issue after some additional testing.