更改整数的默认NumberStyles?

时间:2014-01-17 15:08:41

标签: c# asp.net-mvc parsing model-binding

我有一个具有整数属性的模型。使用23443提交模型时,模型绑定器工作正常,并且该操作中的值可用。但是,如果使用千位分隔符23,443提交模型,则不会解析该值,并且属性为零。但我发现一个十进制类型的属性可能有千位分隔符,它会解析并正确填充。

我发现by default Int32.Parse() doesn't parse thousands separatorDecimal.Parse()确实允许千位分隔符。我不想写一张支票,如:

public ActionResult Save(Car model, FormCollection form) {
    Int32 milage;
    if(model.MyProperty == 0 && Int32.TryParse(form["MyProperty"], NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out milage) {
        model.MyProperty = milage;
    } else
        ModelState.AddModelError("Invalid", "Property looks invalid");

    [...]
}

每次我处理这些领域。它看起来很丑陋,并将所有验证移出模型属性。将属性的类型更改为十进制只是为了使模型绑定工作似乎不是一个明智的想法。当我查看模型绑定器时,看起来它正在使用TypeConverter来完成从字符串到类型的转换。它looks like Int32Converter uses Int32.Parse() with NumberStyles.Integer

是否有办法更改Int32Converter的行为以允许默认情况下解析千位分隔符?也许在整个应用中覆盖NumberStyles上的默认Int32.Parse()?或者是添加我自己的模型绑定器,用NumberStyles.AllowThousands解析整数只有/正确的行动方案?

1 个答案:

答案 0 :(得分:0)

我认为,您可以为int类型添加自定义绑定器。

演示:http://dotnetfiddle.net/VSMQzw

有用的链接:

<强>更新

基于Haacked文章:

using System;
using System.Globalization;
using System.Web.Mvc;

public class IntModelBinder : IModelBinder
{
    #region Implementation of IModelBinder

    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    {
        ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        ModelState modelState = new ModelState { Value = valueResult };
        bindingContext.ModelState[bindingContext.ModelName] = modelState;

        object actualValue = null;
        try 
        {
            actualValue = Int32.Parse(valueResult.AttemptedValue, NumberStyles.Number, CultureInfo.InvariantCulture);
        }
        catch (FormatException e) 
        {
            modelState.Errors.Add(e);
        }

        bindingContext.ModelState.Add(bindingContext.ModelName, modelState);
        return actualValue;
    }

    #endregion
}

在Application_Start事件中(可能在Global.asax中),添加:

ModelBinders.Binders.Add(typeof(int), new IntModelBinder());