【问题标题】:ASP.NET MVC3 ValueProvider drops string input to a double propertyASP.NET MVC3 ValueProvider 将字符串输入拖放到双属性
【发布时间】:2012-10-22 22:34:55
【问题描述】:

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

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

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

这是ValueProvider 的预期行为吗?有没有办法让ValueProvider 在没有实现自定义ValueProvider 的情况下报告转换失败?谢谢!

【问题讨论】:

  • 用RequiredAttribute装饰字段。
  • 您能否为模型显示一点代码以及视图所需的那一点点代码,因为我已经对其进行了测试,ModelState.IsValid 是false 用于接收文本的double。
  • @Silvermind - 你确定你不是指double?
  • @MystereMan 对不起,我的错。我的意思是双重提交的文本,但我在 ASP.NET MVC4 上对其进行了测试;)
  • @Silvermind - 我想这还不清楚。这 ?位于代码括号内,表示可以为空的双精度。你确定你不是指可空的double? 而是double?

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


【解决方案1】:

这里的部分问题是您的模型的类型为double。

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

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

【讨论】:

  • 不错的解决方案。验证器的奇怪行为很难。我仍然会检查 MVC4,因为我很好奇它是否也发生在那里。
  • ASP.NET MVC4 将正确处理它,因此将文本提交到不可归属且不可为空的 double 属性将设置 ModelState.IsValid = false 并显示消息:The value 'foo' is not valid for MyDouble.
  • @Silvermind - 感谢您的关注。我想知道这是否是 MVC4 的改进
  • @MystereMan 谢谢,将MyDouble 更改为double? 并用[Required] 装饰它就完成了。 ModelState 返回无效,错误为 "MyDouble is required"。不是对实际发生的事情的最准确描述,但在我的情况下足以确定提交了错误的输入。
  • @Silvermind 这是个好消息。升级后,我很乐意清理此修复程序。
【解决方案2】:

您可以通过实现 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();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-21
    • 1970-01-01
    • 1970-01-01
    • 2018-03-10
    • 2017-08-29
    • 2013-07-06
    • 2011-07-27
    相关资源
    最近更新 更多