【问题标题】:Change default NumberStyles on integers?更改整数的默认 NumberStyles?
【发布时间】:2014-04-24 22:39:01
【问题描述】:

我有一个具有整数属性的模型。当使用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 的行为以允许默认解析千位分隔符?也许覆盖整个应用程序中Int32.Parse() 上的默认NumberStyles?还是添加我自己的模型绑定器,它用NumberStyles.AllowThousands 解析整数是唯一/正确的行动方案?

【问题讨论】:

  • 我不确定您的问题的答案是什么,但您可能会遇到与其他数据类型(可能是 DateTime 的)类似的格式问题。我的建议是在这些情况下使用字符串属性并自己解析它,而不是试图强制模型绑定器以不同的方式表现。
  • @Ryan 嗯...你是说应该将模型属性更新为字符串,而不是数字类型?
  • 意思是,你有一个public string MyNumber {get;set;} 捕获用户实际提交的内容,还有一个internal int ParsedMyNumber { ... } - 在其中,你解析getter 中的字符串值(去掉千位分隔符)。
  • 您还可以创建一个 CarViewModel 以便您的汽车模型保持美观和干净。如果你总是在你的视图和你的模型之间放置一个视图模型,那么你总是有一个方便的地方来放置这样的东西。
  • 自定义模型绑定器属性怎么样?然后,您可以在模型上装饰任何需要使用 AllowThousands 轻松干净地解析的 int - 我只是认为整个类型的模型绑定器可能有点过头了 - 特别是如果您有其他类型需要拥有int 用 AllowThousands 解析。

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


【解决方案1】:

我认为,您可以为 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());

【讨论】:

  • 我没有在任何真正的asp.mvc项目中测试过。
  • 我想到了一个自定义模型活页夹。我不确定是否有比这样做更好的方法。另外,您可以编辑您的帖子以包含代码吗?如果 dotnetfiddle 出现故障,代码将永远丢失。 More information
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-15
  • 1970-01-01
  • 1970-01-01
  • 2015-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多