1

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

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

然后我在对应的文本框中填写“foo”myDouble并提交表单。检查controllerContext.HttpContext.Request.Form表明myDouble=foo,这是我所期望的。然而,bindingContext.ValueProvider.GetValue("myDouble") == nullbindingContext.ModelState.Count == 5(确切的数字并不重要,但它比以前少一个)。查看ValueProvider, 就好像myDouble从未提交过,并且模型绑定就像没有提交一样。这使得很难区分错误输入和无输入。

这是预期的行为ValueProvider吗?有没有办法ValueProvider在转换失败而不实现自定义时进行报告ValueProvider?谢谢!

4

2 回答 2

1

这里的部分问题是您的模型具有double.

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

您应该通过使用然后向该属性添加一个Required 属性来使该属性可以为double空。double?如果不需要类型,则可以添加正则表达式验证器。

于 2012-10-22T22:48:08.237 回答
0

您可以通过实现 IModelBinder 来实现自定义模型绑定逻辑。这会将数据验证逻辑置于模型绑定级别 - 因此可用于任何类型的 ValueProvider。在您的情况下,模型绑定器将确定当 myDouble = "foo" 不是双精度时,并向显示无效值的 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();
}
于 2012-10-22T22:58:45.413 回答