ASP.NET MVC3 ValueProvider将字符串输入删除为double属性

时间:2012-10-22 22:34:56

标签: asp.net-mvc-3 model-binding value-provider

我正在尝试验证文本框的输入,该文本框对应于模型中double类型的属性。如果用户输入"foo"我想知道它,那么我可以显示错误。但是,ValueProvider正在静默删除值(没有错误添加到ModelState)。

在正常提交中,我填写"2"以查找与myDouble对应的文本框并提交表单。 检查controllerContext.HttpContext.Request.Form会显示myDouble=2以及其他正确的输入。正如预期的那样bindingContext.ValueProvider.GetValue("myDouble") == 2bindingContext.ModelState.Count == 6bindingContext.ModelState["myDouble"].Errors.Count == 0。一切都很好,模型按预期结合。

然后我为“{1}}对应的文本框填写”foo“并提交表单。 检查myDouble会显示controllerContext.HttpContext.Request.Form,这是我的预期。但是,myDouble=foobindingContext.ValueProvider.GetValue("myDouble") == null(确切的数字并不重要,但它比以前少了一个)。查看bindingContext.ModelState.Count == 5,就好像ValueProvider从未提交过,模型绑定就好像不是一样。这使得难以区分输入错误和无输入。

这是myDouble的预期行为吗?有没有办法让ValueProvider报告转化失败而不实施自定义ValueProvider?谢谢!

2 个答案:

答案 0 :(得分:1)

此处的部分问题是您的模型的类型为double

问题是double不能为空,因此默认值为0,因此提交..如果ValueProvider返回null,则该字段的值仍为0,验证将通过。

您应该使用double使double?为空,然后将属性添加到必需属性中。如果不需要该类型,则可以添加正则表达式验证器。

答案 1 :(得分:0)

您可以通过实现IModelBinder来实现自定义模型绑定逻辑。这将使数据验证逻辑处于模型绑定级别 - 因此可用于任何类型的ValueProvider。在您的情况下,模型绑定器将确定当myDouble =“foo”不是double时,并向显示无效值的ModelState错误添加异常。

public class CustomDoubleBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (controllerContext == null)
        {
            throw new ArgumentNullException("controllerContext");
        }
        if (bindingContext == null)
        {
            throw new ArgumentNullException("bindingContext");
        }
        decimal tempDouble = 0m;
        if (bindingContext.ValueProvider.GetValue(bindingContext.ModelName) != null)
        {
            if (double.TryParse(bindingContext.ValueProvider.GetValue(bindingContext.ModelName).AttemptedValue, out tempDecimal))
            {
                bindingContext.ModelState[bindingContext.ModelName].Errors.Add("Error parsing double value: " + bindingContext.ValueProvider.GetValue(bindingContext.ModelName).AttemptedValue);
            }
        }

        return tempDouble;
    }
}

创建此自定义模型绑定器后,您需要在Global.asax中注册它:

protected void Application_Start()
{
   ModelBinders.Binders[typeof(double)] = new CustomDoubleBinder();
}