Decimal.Parse Chrome和Firefox上的奇怪行为

时间:2016-11-23 19:13:50

标签: c# .net asp.net-mvc google-chrome firefox

在MVC项目中,我的项目的web.Config中有一个变量集,如下所示:

enter image description here

然后在我的代码中,我得到该变量并将其解析为十进制:

enter image description here

enter image description here

正如您所看到的,这很好用,问题是当我在Google Chrome或Mozilla Firefox上运行代码时,我会得到不同的结果:

enter image description here

enter image description here

我不明白为什么会发生这种情况,因为在Chrome上运行网络的所有机器都没有发生,我只能想到它似乎是浏览器配置上的东西,但它是标准的安装,没有什么不同。

任何人都能指出我正确的方向吗?或者知道可能导致这种行为的原因是什么?

更新

文字中的代码(我不知道原因,但确定)

为了便于调试,我有这个:

    public static decimal ServiceFee
    {
        get
        {
            var webConfigVar = ConfigurationManager.AppSettings["ServiceFee"];
            decimal webConfigVarDecimal = decimal.Parse(webConfigVar ?? "0");
            return webConfigVarDecimal;
        }
    }

通常,就像这样

    public static decimal ServiceFee
    {
        get
        {
            return decimal.Parse(ConfigurationManager.AppSettings["ServiceFee"] ?? "0");
        }
    }

和Web.Config

    <appSettings>
        <add key="ServiceFee" value="0.024" />
    </appSettings>

更新2

我知道代码在服务器上运行,但唯一的区别是浏览器,它总是在几台机器上使用这些浏览器。

无论服务器是在本地运行还是在生产

1 个答案:

答案 0 :(得分:3)

Decimal.Parse使用当前请求请求处理线程的CultureInfo,ASP.NET可以(尽管不是默认情况下)根据浏览器的Accept标头设置 - 以便浏览器设置为法语或德语将使用其格式规则(其中逗号','是基数位置,而不是点'.')。这可能是正在发生的事情:您的Chrome浏览器设置为使用不同的文化。

修复是在调用任何CultureInfo.InvariantCultureParse方法时指定ToString,如果它与人类可读的文本进行交互(例如,在加载配置文件时)。

这就是静态分析很重要的原因(Visual Studio中的“分析”菜单) - 它可以指出这些错误。

(我个人认为Parse方法应该从.NET中删除,并替换为显式ParseFormatted(IFormatProvider, String)ParseInvariant(String) - 但这只是我:)

我注意到始终在属性获取器中调用Parse是低效的。您应该静态缓存它(使用新的C#6.0只读属性语法):

using System.Globalization;

public static decimal ServiceFee { get; } =
        Decimal.Parse(
            ConfigurationManager.AppSettings["ServiceFee"] ?? "0",
            NumberStyles.Number,
            CultureInfo.InvariantCulture
        );

如果您经常这样做,您可能需要一个可重复使用的方法:

public static Decimal GetAppSettingDecimal(String name) {

    String textualValue = ConfigurationManager.AppSettings[ name ];
    Decimal ret;
    return Decimal.TryParse( textualValue, NumberStyles.Number, CultureInfo.InvariantCulture, out ret ) ? ret : 0;
}

public static Decimal ServiceFee { get; } = GetAppSettingDecimal("ServiceFee");