Description
IgbSlider.GetCurrentValueAsync() (and its sync twin GetCurrentValue()) can return a wrong value, or throw an unhandled exception, depending on the browser's locale.
The returned value is parsed with double.Parse() without an explicit culture. This uses the current thread culture, and Blazor WebAssembly sets that culture from the browser's navigator.language.
When the locale uses a comma as the decimal separator (for example de-DE), a fractional value can be parsed into a much larger number. When the locale does not accept a period at all (for example fr-FR), the parse throws a FormatException that is not caught anywhere.
Data binding (@bind-Value and the ValueChanged event) is not affected. It goes through a different code path that is already culture safe. Only the explicit GetCurrentValueAsync() / GetCurrentValue() calls are affected.
Most apps read the slider value through data binding, so this bug may not hit many real projects. Still, GetCurrentValueAsync() is a public API and should return a correct value.
I found the same coding pattern (an async Get...Async() method that parses a double return value the same way) in a few other components. I have not verified these, but they are likely to have the same problem.
IgbCarousel.GetTotalAsync() / GetTotal()
IgbCarousel.GetCurrentAsync() / GetCurrent()
IgbHighlight.GetSizeAsync() / GetSize()
IgbHighlight.GetCurrentAsync() / GetCurrent()
IgbRating.GetCurrentValueAsync() / GetCurrentValue()
I reproduced this against a local build of the master branch, so it is not specific to any feature branch.
Hosting Model
Blazor WebAssembly
.NET Version
10.0 (the affected code is not framework specific, so earlier target frameworks are likely affected too)
Ignite UI for Blazor Version
Reproduced against a local build of master
Component / Area
Slider / Range Slider
Browser
Edge
Operating System
Windows
Steps to Reproduce
- Create a Blazor WebAssembly app and add the sample code below.
<main>
<div>
<p>Bound Value: @_boundValue</p>
</div>
<div>
<p>
<span>Retrieved Value: @_retrievedValue</span>
<span>
<IgbButton @onclick="RefreshValue">
GetCurrentValueAsync
</IgbButton>
</span>
</p>
</div>
<IgbSlider @ref="_sliderRef"
Min="0"
Max="3"
Step="0.5"
PrimaryTicks="4"
SecondaryTicks="1"
HideSecondaryLabels
@bind-Value="_boundValue">
</IgbSlider>
</main>
@code
{
private IgbSlider? _sliderRef;
private double _boundValue = 1.0;
private double? _retrievedValue;
private async Task RefreshValue()
{
if (_sliderRef is not null)
{
_retrievedValue = await _sliderRef.GetCurrentValueAsync();
}
}
}
- Set the browser or OS display language to German (
de-DE), so navigator.language returns "de-DE".
- Run the app. Move the slider to a value with a fractional part, for example
1.5.
- Click the
GetCurrentValueAsync button and check the "Retrieved Value" line.
- Repeat with the display language set to French (
fr-FR).
Actual Result
With de-DE, the retrieved value is wrong. For example, a slider value of 1.5 comes back as 15, with no error at all.
With fr-FR, clicking the button throws an unhandled FormatException from GetCurrentValueAsync() whenever the slider value has a fractional part.
In both cases, the "Bound Value" line always shows the correct value.
Expected Result
GetCurrentValueAsync() (and GetCurrentValue()) should return the correct value, no matter what locale the browser uses.
Reproduction URL
Attachments
I will attach a sample project
📦BlazorWasmApp1.zip
Description
IgbSlider.GetCurrentValueAsync()(and its sync twinGetCurrentValue()) can return a wrong value, or throw an unhandled exception, depending on the browser's locale.The returned value is parsed with
double.Parse()without an explicit culture. This uses the current thread culture, and Blazor WebAssembly sets that culture from the browser'snavigator.language.When the locale uses a comma as the decimal separator (for example
de-DE), a fractional value can be parsed into a much larger number. When the locale does not accept a period at all (for examplefr-FR), the parse throws aFormatExceptionthat is not caught anywhere.Data binding (
@bind-Valueand theValueChangedevent) is not affected. It goes through a different code path that is already culture safe. Only the explicitGetCurrentValueAsync()/GetCurrentValue()calls are affected.Most apps read the slider value through data binding, so this bug may not hit many real projects. Still,
GetCurrentValueAsync()is a public API and should return a correct value.I found the same coding pattern (an async
Get...Async()method that parses adoublereturn value the same way) in a few other components. I have not verified these, but they are likely to have the same problem.IgbCarousel.GetTotalAsync()/GetTotal()IgbCarousel.GetCurrentAsync()/GetCurrent()IgbHighlight.GetSizeAsync()/GetSize()IgbHighlight.GetCurrentAsync()/GetCurrent()IgbRating.GetCurrentValueAsync()/GetCurrentValue()I reproduced this against a local build of the
masterbranch, so it is not specific to any feature branch.Hosting Model
Blazor WebAssembly
.NET Version
10.0 (the affected code is not framework specific, so earlier target frameworks are likely affected too)
Ignite UI for Blazor Version
Reproduced against a local build of
masterComponent / Area
Slider / Range Slider
Browser
Edge
Operating System
Windows
Steps to Reproduce
de-DE), sonavigator.languagereturns"de-DE".1.5.GetCurrentValueAsyncbutton and check the "Retrieved Value" line.fr-FR).Actual Result
With
de-DE, the retrieved value is wrong. For example, a slider value of1.5comes back as15, with no error at all.With
fr-FR, clicking the button throws an unhandledFormatExceptionfromGetCurrentValueAsync()whenever the slider value has a fractional part.In both cases, the "Bound Value" line always shows the correct value.
Expected Result
GetCurrentValueAsync()(andGetCurrentValue()) should return the correct value, no matter what locale the browser uses.Reproduction URL
Attachments
I will attach a sample project
📦BlazorWasmApp1.zip