aspnetcore: [Blazor WASM] InputSelect: binding no longer works with negative numbers
Is there an existing issue for this?
- I have searched the existing issues
Describe the bug
Data binding to an html input <input @bind="xyz"> OR <InputSelect @bind-Value="xyz"> no longer works with negative numbers (-1). Only an empty select is rendered (value of select in inspector is empty string)
Unsure when it stopped working, but i’m pretty sure this worked in 6.0.0 as I have components explicitly built that uses negative numbers (to support nullable enum and and optional grpc enum)
Expected Behavior
Binding to write the negative number to the select element, so the negative values can be displayed and selected.
Steps To Reproduce
<select @bind="@myValue">
<option value="-1">-1</option>
<option value="0">0</option>
<option value="1">1</option>
</select>
@code {
private int myValue = -1;
}
- Select shows up as empty on load
- Selecting positive number works as expected
- Selecting a negative number, the select again becomes emtpy.
Exceptions (if any)
No response
.NET Version
6.0.300
Anything else?
ASP.NET Core 6.0.5 Visual Studio 17.2.3
dotnet --info
.NET SDK (reflecting any global.json):
Version: 6.0.300
Commit: 8473146e7d
Runtime Environment:
OS Name: Windows
OS Version: 10.0.19043
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\6.0.300\
Host (useful for support):
Version: 6.0.5
Commit: 70ae3df4a6
.NET SDKs installed:
3.1.302 [C:\Program Files\dotnet\sdk]
3.1.401 [C:\Program Files\dotnet\sdk]
3.1.418 [C:\Program Files\dotnet\sdk]
5.0.101 [C:\Program Files\dotnet\sdk]
5.0.404 [C:\Program Files\dotnet\sdk]
5.0.407 [C:\Program Files\dotnet\sdk]
6.0.300 [C:\Program Files\dotnet\sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 3.1.22 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.24 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.16 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 3.1.22 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.24 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.16 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.1.22 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.24 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.13 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.16 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 19 (18 by maintainers)
Thanks for all your brain power! Personally I would have expected the
valueattribute to be invariant-culture and agree with @Eilon. But as for the workaround to use strings and having to do manual conversion logic for each field is a big pain. I think the suggested workaround should rather be as we have discussed here to use@(-1).@TanayParikh, for completeness, I just installed .NET7-p7 and still could repro using my original snippet.
Yeah, I don’t really see an argument for those literal strings to be treated as culture-invariant. It seems more likely that they are culture unknown, but most likely in the culture of whoever typed them.
I think that logically the
valueof an<option>is culture-invariant, because those values are strictly server-supplied, and servers logically operate as “invariant culture.” However, because “things are complicated” and “the server doesn’t really know what the client is doing” and “it’s a breaking change” I understand entirely that it’s not something we could really change. (Here in Blazor WASM there’s no “server” but you can take it to mean the “logic behind the page”.)Historically one way we’ve suggested for people to work around this is to always bind values to strings, and then in the class being bound to, have some logic that parses the string however you want (whatever culture you want, trim spaces, do conversions, etc.).
@TanayParikh Thanks for continuing the investigation!
I agree it looks like there’s no further problem relating to the minus character in Swedish culture, since that now seems to be accepted for culture-specific parsing.
However, the underlying question about whether we should be doing culture-specific parsing at all for
<select>and<input type="radio">is still worth us thinking through clearly. To illustrate the difference, I’ve created a test case at https://blazorrepl.telerik.com/wwEsuXuN56lSQqKn02. That’s running on .NET 6, but behaves the same on 7 too.The behavior is:
en-USoren-GB), then all the dropdowns work@((3.5).ToString(CultureInfo.InvariantCulture))renders as the string3.5, but when we try to parse that culture-sensitively, it just doesn’t parse. Similarly, if themyValuefield already holds the number three-point-five, then it doesn’t match any of the<option>values since it gets formatted as3,5and no option has a value with that string.Yesterday I thought it was quite clear we should be doing culture-invariant parsing/formatting for
<select>and<input type="radio">values, but on further consideration I’m not so sure. The unavoidable truth is that those elements have string values, not numeric values. Whether you want to parse as culture-invariant or specific depends on whether you previously formatted the choices as culture-invariant or specific, and that’s not something that Blazor controls, unless we choose to change how it works.For example, if your
.razorsource code includes:… then those two
<option>elements are literal HTML text, and Blazor doesn’t interfere with their contents at all. It’s up to the developer to type out the values as strings in the right culture.Whereas if your source code includes the same except:
… now Blazor does format the C# number literal as a string for you, and our default is to format all output as culture-specific, since it’s usually used for display to the user. We could look into keeping track of the context of where a given value was being outputted, and varying the display format, but that’s a whole new complexity we don’t deal with today.
So overall, our existing culture-sensitive parsing for
<select>and<input type="radio">:@someValue, because that will dynamically vary the format to match each user@(someValue.ToString(CultureInfo.InvariantCulture)), because our culture-specific parsing will fail if the user isn’t in an invariant-like cultureI don’t think we really can change it to be culture-invariant by default, because then we’d require developers to always either:
.ToString(CultureInfo.InvariantCulture), which they also won’t remember to do… and of course it would be a very breaking change.
One person in the meeting who seemed to have a clear preference yesterday was @Eilon - do you have any feedback on this?
Anyone else?
@TanayParikh, thanks for looking into this. I have yet to install .NET7, will have to get back to you later.
No errors in console.
I think I maybe managed to narrow it down somewhat by stepping the minified JS:
It’s after the linked line the select goes blank: https://github.com/dotnet/aspnetcore/blob/v6.0.5/src/Components/Web.JS/src/Rendering/BrowserRenderer.ts#L582
If I, while at the break-point, edit and reset the value to be written (just writing “-1” again) it works as expected.
At closer inspection of the string that blazor tries to set for int -1 is using a different character for the minus sign: It tries to write
"−1"(minus) while I think it should be"-1"(hyphen-minus) which is what I can type on my keyboard and what is used for the int.Something way back in my head tells me I’ve seen a similar issue with javascript in the past. Can it be culture setting regarding number formatting? I saw somewhere in the same JS file that
JSON.parse()was used to convert the value?