Feed Subscribe
Exception has been thrown by the target of an invocation.


Globalization is not an enemy

by ondrejsv 9. December 2009 18:36

System.FormatException: Input string was not in a correct format. The exception I see again and again because I’m running an English Windows 7 with Slovak regional settings and some developers just can’t imagine there are regions in the world where the decimal separator is not a period (.) but a comma (,) or where they use more than 12 hours a day. It’s unfortunate for them because many more people live outside the USA so reach of their application is far less than it could be.

Today I want to build a demonstration utilizing a Ribbon bar in my Silverlight application and I found one. A sample was attached but it crashed immediately after start with the aforementioned exception. The Ribbon control stores some default brushes in an XML file and parses on its own with code like this:

string xStr = pointAsString.Substring(0, pointAsString.IndexOf(","));
string yStr = pointAsString.Substring(pointAsString.IndexOf(",") + 1);

return new Point(double.Parse(xStr), double.Parse(yStr));

If we take a look at a fragment of the XML:


<LinearGradientBrush Name="GroupedButtonSemiHighlight" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#FFFEF7" Offset="0.0" />
<GradientStop Color="#FFF7DF" Offset="0.5" />
<GradientStop Color="#FFEEBE" Offset="0.6" />
<GradientStop Color="#FFF6DD" Offset="1.0" />
</LinearGradientBrush>

we see that it cannot succeed on any client configuration which does not use a point as decimal separator because the double.Parse method without providing an IFormatProvider would parse the string using the current regional settings.

If you write code that parses numbers from a content not edited or viewable directly by users and don’t want to take regional settings into account, always use the Invariant Culture as your IFormatProvider.

So I fixed the code:

string xStr = pointAsString.Substring(0, pointAsString.IndexOf(","));
string yStr = pointAsString.Substring(pointAsString.IndexOf(",") + 1);

return new Point(double.Parse(xStr, CultureInfo.InvariantCulture), double.Parse(yStr, CultureInfo.InvariantCulture));

More detailed information on internationalization, globalization and localization issues can be found on the Globalization Step By Step Microsoft site.

kick it on DotNetKicks.com [digg]

Tags:

Comments (3) -

12/15/2009 11:40:13 AM #

Lukas Zdechovan

It&#39;s a very useful article, I also plan to play with the Ribbon bar so I&#39;ll follow your fix to avoid problems Smile
I&#39;ve come across with the InvariantCulture in DateTime parse errors caused by input in diff culture than user&#39;s one.

Lukas Zdechovan Slovakia |

2/18/2010 3:19:43 PM #

Lukas Zdechovan

I was just facing the problem with Parsing double from user&#39;s input and I found out, that it doesn&#39;t parse correctly with just InvariantCulture as FormatProvider.
I made a simple console app to test it with string s = &amp;quot;100,4&amp;quot; and tried to parse double from it &amp;gt; double.Parse(s, CultureInfo.InvariantCulture); I was surprised but the resulted value was 1004, not the 100.4. Maybe the parse method takes the comma as thousands separator and just removes it. Than I changed it to double.Parse(s, CultureInfo.CurrentCulture), but it still works correctly only if the input is already in correct culture format. Otherwise it doesn&#39;t throw an exception but returns 1004 as with the InvariantCulture.

Lukas Zdechovan Slovakia |

2/18/2010 8:09:06 PM #

ondrej

Lukas,

this behavior is expected. InvariantCulture uses commas as thounsand separator and periods as decimal separator (in fact, it is based on the English culture). CurrentCulture mirrors by default Windows regional settings, so if you have Slovak regional settings, &amp;quot;100,4&amp;quot; would be parsed as 100 + 4/10 against CurrentCulture. If you had English regional settings, the same result would be given by &amp;quot;100.4&amp;quot; input string. On the other hand, InvariantCulture is always same (actually, that is what invariant means Smile) and purposely does not reflect user regional settings. It&#39;s used for parsing configuration settings and other inputs which the user does not enter and their values should look same whatever regional settings are. Hope it makes clear.

ondrej Slovakia |

Pingbacks and trackbacks (1)+

Comments are closed