接受逗号和点作为小数分隔符

时间:2013-01-18 14:09:34

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

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

我应该为decimal类型实现自己的Value Provider(或事件Model Binder),还是我错过了一些简单的方法来执行此操作?

4 个答案:

答案 0 :(得分:38)

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

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

答案 1 :(得分:5)

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

Convert.ToDecimal(valueProviderResult.AttemptedValue);

的选定答案中

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

答案 2 :(得分:3)

由于接受了答案,我最终得到了以下实现来处理float,double和decimal。

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方法

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

答案 3 :(得分:1)

var nfInfo = new System.Globalization.CultureInfo(lang, false)
{
    NumberFormat =
    {
        NumberDecimalSeparator = "."
    }
};
Thread.CurrentThread.CurrentCulture = nfInfo;
Thread.CurrentThread.CurrentUICulture = nfInfo;