Inconsistent DecimalSeparator value - c#

When I apply toString() on a number of type double, I get the string with . as the decimal separator. In one of my projects only, I get , as the decimal separator.
I have not changed CultureInfo data. My CurrentCulture is el-GR in all my projects which is the default system Culture. el-GR uses , as the decimal separator but I have changed this value through Windows Regional Settings to . which is reflected correctly to all my projects except the one in question.
The only difference I can tell is that it is a Web Site and not a usual Visual Studio Project. I do not know if this forces Visual Studio NOT to take into account the local computer NumberFormat exceptions and if/how this can be changed.

The CultureInfo your program use, if you don't explicitly set it somehow in code, is related to Regional Settings of current user.
When running a web project, very likely current user is not you, the one logged in in the computer, but a built-in user IIS uses. see this question and display somehow current user to find out if your problem is actually related to this.
To change regional settings for your (.Net & IIS hosted) web application, you can use different method: web.config of your application, web.config of the whole server, settings for IIS, or even tweak the registry.
Have a look at this thread (and also linked threads you find in the left column) for methods you can use.

Related

HttpContext.Current.Request.UserLanguages is NULL when first loading IE11/Edge in European countries

I support an application (c#/asp.net) that uses multiple languages using .Resx files for numerous European countries. Recently, some users upgraded to Windows 10 and thus Internet Explorer 11. Now when they load the application, it defaults the main page to en-US and when they go to a page that calls a function that references HttpContext.Current.Request.UserLanguages[0], it comes back as NULL, thus causing a crash with a NULL reference error.
If they change their language settings in any way (add, remove or move a language up or down), then HttpContext.Current.Request.UserLanguages[0] is populated with that top language. However, once they reboot their machine and re-open IE11, then the field is NULL again until they change their settings yet again.
How can I set/detect the correct language without having the user to change their language settings every time they open IE11 after a reboot?
This error does not happen in Chrome, but some users may not have access to Chrome.
Notes I have discovered from past research and are currently in my project:
All pages have Culture="auto" and UICulture="auto";
When first loading the application, System.Threading.Thread.CurrentThread.CurrentUICulture = en-US (and not their default language); (same goes for CurrentCulture as well - both are initially set to en-US)
After they change their language settings, then System.Threading.Thread.CurrentThread.CurrentUICulture changes to be their set language (e.g.: fr-CH for French Swiss);
To summarize: How do I detect IE11's language setting for the user when Request.UserLanguages is NULL and when the CurrentThread.CurrentUICulture is defaulting to en-US and not their system's language? Is there a workaround for using Request.UserLanguages?
I had a user go into Edge and try it out and the same problems occur. The application is not picking up the local culture/language - it is defaults to en-US and not en-UK or fr-CH for example. Also, the application is coded to check different cultures to display dates in the format of the culture, so for Europe, the DD/MM/YYYY format is needed and US - MM/DD/YYYY; currency is also different. So I need to be able to detect the correct culture in Windows 10 without having the user change their language settings to set HttpContext.Current.

CultureInfo("fr-BE") different on Windows 8.1 than before

I set the culture for an .NET web app in order to use specific format for numbers, currency and date:
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("fr-BE");
On an Windows 2008 server machine with IIS 7 I get "d/m/yy" as short date format (what I want).
On my (new) Windows 8.1 pro machine (developer and test) I get "d-m-yy" format for the same CultureInfo..."dash" instead of "slash" separator.
I've checked also in Control Panel -> Region and the settings for French(Belgium) are as mentioned above, different in W2k8 server than in W8.1pro...
The .NET version is 4, which is ok. Invariant culture doesn't help, as far as I need specific culture to display in the UI and the problem was there. It is true, changes came with Windows 8... Finally I used to override some settings for the Thread culture, like the Date Separator:
DateTimeFormatInfo dtfi = Thread.CurrentThread.CurrentCulture.DateTimeFormat; if (dtfi.DateSeparator != "/") dtfi.DateSeparator = "/";
This ensure that slash will be the date separator all the time in the current thread.
Thank you.
Does anybody knows about it? Belgium changed national standards? Or, Microsoft did for them? Any idea?
Thanks.
Thanks for the answers. .NET version is 4, which is ok. Invariant culture doesn't help, as far as I need specific culture to display in the UI and the problem was there. It is true, changes came with Windows 8...
Finally I used to override some settings for the Thread culture, like the Date Separator:
DateTimeFormatInfo dtfi = Thread.CurrentThread.CurrentCulture.DateTimeFormat;
if (dtfi.DateSeparator != "/") dtfi.DateSeparator = "/";
This ensure that slash will be the date separator all the time in the current thread.
Thank you.
I was looking at similar issue for CultureInfo 'en-NZ', as it been changed for the same culture setting in different Windows version, and cause my web service saved different strings for the same CultureInfo, and it turns out it is provided by Windows since .Net Framework 4, and was a combination of Windows and .Net before that.
Lucky for me, I can make use of Invariant culture, which was recommended by Microsoft to make sure the string I saved into Database not going to be changed because of Windows or future .Net Framework update. The thing is, for my case it was the AM\PMDesignator changed from a.m.\p.m. to AM\PM, and the Invariant culture will make sure it saves to AM\PM I assume it will not change in the future, but if I want it save to a.m.\p.m. as it was for older version of Windows, Invariant culture wouldn't be able to do that, I will probably need define my own custom culture or overwrite the current culture as you did.
See the other question about Microsoft specified that CultureInof are subject to change without notice

Convert.ToDouble("4089.90") outputs 40.899,00 why?

I am developing a software that uses number precision, but I have this problem, it happens that when I take a string to convert to double it outputs me with a different culture.
For example I use
Convert.ToDouble("4089.90"); // it outputs 40.899,00
Is strange cause in my computer it works OK but on the client's PC (with the same culture in regional settings) shows me the latter output. I know I can fix it using
Convert.ToDouble("4089.90", System.Globalization.CultureInfo.InvariantCulture);
But there is a lot of code in the program using "Convert.ToDouble" and I wouldn't like to change all of it, on the other hand I want to understand why this happens.
You can set the culture for your thread with:
Thread.CurrentThread.CurrentCulture =
System.Globalization.CultureInfo.InvariantCulture;
You don't say where you are based, but the output is consistent with the current culture being one that has "." as the thousands separator and a decimal comma rather than a decimal point.
However, you state that the culture is the same - which contradicts this. Have you or the client changed (or customised) the "Standards and formats" on the Regional and Language Options? If the setting has been customised it will still read as "English (United Kingdom)" (or where ever) but will produce different results to the default.
I know neither c# nor asp.net, but I think the problem is this: You are performing the operation in a culture where the dot . is the thousands separator and not the decimal separator. The very output you quote is the proof: 40.899,00.
What culture/locale are you working in?
Culture could be based on where the ASP.Net application is running, and not the client PC that is running the browser. While their desktop PC might have similar culture settings, the server may differ.
It is your computer that is not giving the correct answer, not theirs. Your culture states that "4089.90" is the same as 4089900, since the dot (.) is used for separating thousands (and thus there should be three numbers after the dot).
It appears you want to use the dot as a decimal-separator, contrary to your culture settings; so you have to use System.Globalization.CultureInfo.InvariantCulture in your program. Sorry.
Actually is very rare this behaviour cause all the machines have the same culture settings, however I think that the best solution would be to modify the web.config like this:
configuration>
<system.web>
<globalization culture = "es-HN" />
</system.web>
</configuration
And apply the settings for the entire application.
Thanx everyone for your assistance.

How does a .NET process get the culture information?

I have a Windows service running (C#, .NET 2.0) on Windows Server 2003 R2. In one server the System.Threading.Thread.CurrentThread.CurrentCulture is {en-AU} and in the other {en-US}.
This has caused a difference when calling ToString() on a DateTime object. I want the culture to be {en-AU}.
I checked the "Regional and Language Setting". In both servers, the "Regional Options" tab shows "English (Asutralia)". But in the "Advanced" tab it shows "English (United States)" for one and "English (Australia)" for the other. So this must be causing the difference. Although I want to know why exactly the "Advanced" tab says "the language version of the non-unicode programs you want to use", I thought .NET processes were Unicode and should not be affected by this.
How does the .NET runtime determine the culture to use? Any detailed reference would be helpful.
If a culture has not been set on the thread, Thread.CurrentThread.CurrentCulture defaults to the "user default culture" - which it gets from the underlying OS. This is determined by the Formats section in the regional control panel applet.
For a service, it has no control panel settings by default like for a user (the case above) as it runs under the LocalSystem account which will not have a profile, so it uses the system locale from the OS. I'm not sure if this can be set for a service by adjusting the settings in Windows.
There are a few things you could do:
you can explicitly set the CurrentCulture of the main thread when the service starts. If you do this, you will need to bear in mind that any new threads that are created in your service will also need to have their CurrentCulture set as well, as threads do not inherit their culture from parent threads.
you can set the service to run as a specific user, and set that user's regional settings (the formats section) to be the culture you want to use. When the service starts as that use,it will use that user's regional settings.
since your problem seems to be related to calling DateTime.ToString(), make sure you pass the AU culture to the ToString() method:
DateTime.ToString(new CultureInfo("en-AU"))
You could add this as an extension method to save you having to do this everywhere:
public static string ToAUString(this DateTime dateTime)
{
return dateTime.ToString(new CultureInfo("en-AU"));
}
You can then call DateTime.ToAUString() to get the correct output.
In my case it took only one line of code to change the Culture:
System.Globalization.CultureInfo.DefaultThreadCurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo( "en-US" )
It changes default Culture of Main thread and new ones as well.
This MSDN page on CultureInfo has some information that might be relevant:
The user might choose to override some of the values associated with the current culture of Windows through the regional and language options portion of Control Panel. For example, the user might choose to display the date in a different format or to use a currency other than the default for the culture. In general, your applications should honor these user overrides.
If UseUserOverride is true and the specified culture matches the current culture of Windows, the CultureInfo uses those overrides, including user settings for the properties of the DateTimeFormatInfo instance returned by the DateTimeFormat property, and the properties of the NumberFormatInfo instance returned by the NumberFormat property. If the user settings are incompatible with the culture associated with the CultureInfo, for example, if the selected calendar is not one of the OptionalCalendars, the results of the methods and the values of the properties are undefined.
I think this might be a good starting point for your investigations.

How can I change a Windows user's regional settings/date format?

I use a VB6/COM+ application which outputs date/time values based on the short date settings in the Control Panel, Regional Settings, for the user that runs it. The program that then parses that output has a configurable setting for the date format it expects, and presents in the UI.
e.g. If the regional setting for the user is set to mm/dd/yyyy, and it outputs 06/18/2009, the application expecting "18/06/2009" fails with "String was not recognized as a valid DateTime".
As we usually run this application as a service account, which we have not logged in as interactively to create a profile, we generally set the correct date format and then tick the "Apply all settings to the current user account and the default user profile" option.
I would like to be make the C# configuration utility I have written for this mess to be able to set the date format programmatically for a given user.
Edit
I would like nothing more than to change the code, but do not have the ability to do so at this time.
I also know that what I am asking is a bad thing to do. With regards to "it should be the user's choice" - I am that user, as I create it explicitly for the task; I just want to set the date format by a scripted method, rather than having to do the clicking myself.
This is specifically discouraged by Microsoft. Any solution you may come up with will be a filthy hack that will probably stop working soon.
Think of it this way: who are you to decide those settings? Don't you think that's the user's decision?
Back on topic: find an unambiguous format for the applications to communicate in, such as YYYYMMDD. The application that displays can then simply respect the actual user settings, as it should.
But, since you can't change it, just poke into the registry:
Current user:
HKEY_CURRENT_USER\Control Panel\International
Specific user:
HKEY_USERS\(user SID)\Control Panel\International
Default user:
HKEY_USERS\.DEFAULT\Control Panel\International
sShortDate is probably the value you want to change.
If you are going to modify the profile to suit your needs, why not just ignore the profile settings and hardcode the format you want in your app?
code:
Imports System.Threading
Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US", False)
Microsoft.Win32.Registry.SetValue("HKEY_CURRENT_USER\Control Panel\International", "sShortDate", "M/d/yyyy")
While persistently changing a user's culture (regional settings) is to be done cautiously, there are legitimate use cases.
On Windows 8 and Windows Server 2012 and above, Windows PowerShell comes with the
Set-Culture cmdlet, which is the programmatic equivalent of choosing a different region via Control Panel (intl.cpl).
For instance, Set-Culture fr-CA is the equivalent of interactively choosing region French (Canada) for the current user.
Caveat: Mixed cultures such as en-DE (sic) appear not to work as of Windows PowerShell v5.1 - see this answer of mine.
While it won't be fast, it is possible to call PowerShell commands from C#.

Categories

Resources