【问题标题】:Accept comma and dot as decimal separator [duplicate]接受逗号和点作为小数分隔符[重复]
【发布时间】:2013-01-18 14:09:33
【问题描述】:

ASP.NET MVC 中的模型绑定很棒,但它遵循区域设置。在我的语言环境中,小数点分隔符是逗号 (','),但用户也使用点 ('.'),因为他们懒得切换布局。我希望在一个地方为我的模型中的所有 decimal 字段实现这一点。

我应该为decimal 类型实现我自己的值提供者(或事件模型绑定器)还是我错过了一些简单的方法来做到这一点?

【问题讨论】:

标签: asp.net-mvc modelbinders value-provider


【解决方案1】:

最干净的方法是实现自己的模型绑定器

public class DecimalModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

        return valueProviderResult == null ? base.BindModel(controllerContext, bindingContext) : Convert.ToDecimal(valueProviderResult.AttemptedValue);
        // of course replace with your custom conversion logic
    }    
}

并在 Application_Start() 中注册它:

ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
ModelBinders.Binders.Add(typeof(decimal?), new DecimalModelBinder());

致谢:Default ASP.NET MVC 3 model binder doesn't bind decimal properties

【讨论】:

  • DecimalModelBinder 类放在哪里?
  • @ИванБишевац 我把我的放在\Common\ModelBinders。
  • Convert.ToDecimal(valueProviderResult.AttemptedValue) 适用于逗号,但对于点,数字乘以 100。建议?
  • 感谢这为我节省了一些时间,只是一个小小的改进,请参阅下面的答案。
  • 这个接受的答案并非每次都有效。这取决于错误的当前本地化。
【解决方案2】:

要正确处理组分隔符,只需替换

Convert.ToDecimal(valueProviderResult.AttemptedValue);

在选择的答案中

Decimal.Parse(valueProviderResult.AttemptedValue, NumberStyles.Currency);

【讨论】:

  • 或者 NumberStyles.Any,如果你想大赚一笔。
【解决方案3】:

感谢接受的回答,我最终得到了以下处理浮点数、双精度和小数的实现。

public abstract class FloatingPointModelBinderBase<T> : DefaultModelBinder
{
    protected abstract Func<string, IFormatProvider, T> ConvertFunc { get; }

    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (valueProviderResult == null) return base.BindModel(controllerContext, bindingContext);
        try
        {
            return ConvertFunc.Invoke(valueProviderResult.AttemptedValue, CultureInfo.CurrentUICulture);
        }
        catch (FormatException)
        {
            // If format error then fallback to InvariantCulture instead of current UI culture
            return ConvertFunc.Invoke(valueProviderResult.AttemptedValue, CultureInfo.InvariantCulture);
        }
    }
}

public class DecimalModelBinder : FloatingPointModelBinderBase<decimal>
{
    protected override Func<string, IFormatProvider, decimal> ConvertFunc => Convert.ToDecimal;
}

public class DoubleModelBinder : FloatingPointModelBinderBase<double>
{
    protected override Func<string, IFormatProvider, double> ConvertFunc => Convert.ToDouble;
}

public class SingleModelBinder : FloatingPointModelBinderBase<float>
{
    protected override Func<string, IFormatProvider, float> ConvertFunc => Convert.ToSingle;
}

然后您只需在 Application_Start 方法上设置您的 ModelBinders

ModelBinders.Binders[typeof(float)] = new SingleModelBinder();
ModelBinders.Binders[typeof(double)] = new DoubleModelBinder();
ModelBinders.Binders[typeof(decimal)] = new DecimalModelBinder();

【讨论】:

    【解决方案4】:
    var nfInfo = new System.Globalization.CultureInfo(lang, false)
    {
        NumberFormat =
        {
            NumberDecimalSeparator = "."
        }
    };
    Thread.CurrentThread.CurrentCulture = nfInfo;
    Thread.CurrentThread.CurrentUICulture = nfInfo;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-19
      • 2017-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多