Asp.net mvc 3 ASP.NET MVC3 ValueProvider将字符串输入拖放到双精度属性

Asp.net mvc 3 ASP.NET MVC3 ValueProvider将字符串输入拖放到双精度属性,asp.net-mvc-3,model-binding,value-provider,Asp.net Mvc 3,Model Binding,Value Provider,我正在尝试验证一个文本框的输入,该文本框对应于我的模型中类型为double的属性。如果用户输入了“foo”,我想了解它,以便显示错误。但是,ValueProvider正在无声地删除该值(没有错误添加到ModelState) 在正常提交中,我为myDouble对应的文本框填写“2”,然后提交表单。 检查controllerContext.HttpContext.Request.Form显示myDouble=2,以及其他正确的输入bindingContext.ValueProvider.GetVal

我正在尝试验证一个文本框的输入,该文本框对应于我的模型中类型为
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
?谢谢

这里的部分问题是您的模型有一种类型为
double

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


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

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

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


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

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

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


用RequiredAttribute修饰字段。你能为模型显示一点代码和视图所需的一点代码吗,因为我已经测试了它和
ModelState。对于
double
接收文本,IsValid
false
。@Silvermind-你确定你不是指
double吗?
@MystereMan对不起,我的错了。我的意思是文本要双重提交,但我在ASP.NET MVC4;)上测试了它@Silvermind-我想这还不清楚。这个位于代码括号内,表示可为空的双精度。你确定你不是指可为null的
double吗?
而是
double
?用RequiredAttribute修饰字段。你能为模型显示一点代码和视图所需的那一点吗,因为我已经对它进行了测试,并且
ModelState.IsValid
对于
double
接收文本是
false
。@Silvermind-你确定你不是说
double吗?
@MystereMan对不起,我的错了。我的意思是文本要双重提交,但我在ASP.NET MVC4;)上测试了它@Silvermind-我想这还不清楚。这个位于代码括号内,表示可为空的双精度。你确定你不是指一个可空的
double吗?
而是
double
?很好的解决方案。奇怪的行为对验证器来说很难。我还是要签入MVC4,因为我很好奇它是否也发生在那里。ASP.NET MVC4会正确处理它,因此,将文本提交到非属性且不可为空的
double
属性将设置
ModelState.IsValid=false
,并显示以下消息:
值“foo”对MyDouble无效。
@Silvermind-感谢您的关注。我不知道这是否是一种进步MVC4@MystereMan谢谢,将
MyDouble
更改为键入
double?
,并用
[必需]
对其进行了装饰。
ModelState
返回无效,错误为
“需要MyDouble”
。这不是对实际发生的事情的最准确描述,但在我的例子中已经足够好了,可以确定提交了一个错误的输入。@Silvermind这是个好消息。一旦我们升级,我很乐意清理这个补丁。很好的解决方案