ValidationAttribute的值始终为null

时间:2010-11-30 23:11:38

标签: c# asp.net-mvc data-annotations

这是我写的一个简单的验证属性,用于强制使用仅限数字的字符串(我用它来验证电话号码,邮政编码等):

public class NumericAttribute : ValidationAttribute {

    public NumericAttribute() {
        ErrorMessage = SharedModelResources.ValidationStrings.Numeric; // Message coming from a .resx file
    }

    public override bool IsValid(object value) {

        string stringValue = value as string;

        if (stringValue.IsNotNull())
            foreach (var c in stringValue)
                if (!char.IsDigit(c))
                    return false;

        return true;
    }

}

问题在于,当用于验证字符串以外的其他字符时,假设有十进制,short,int或其他任何内容, object value 总是null。为什么验证仅数字小数?因为如果我不这样做,我会得到默认验证消息'值'x'对'propertyName'无效。我知道默认验证消息的具体问题的解决方案。

我只想了解为什么它始终为空......

BTW,我正在使用VS2008,ASP.NET MVC 2(最终版),.NET 3.5 SP1。

4 个答案:

答案 0 :(得分:1)

您是否肯定value为空,而不只是stringValue

所以说MSDN关于你的as运营商:

  

as运算符就像一个转换器,除了它在转换失败时产生null而不是引发异常。

http://msdn.microsoft.com/en-us/library/cscsdfbt%28VS.71%29.aspx

在该页面的示例中,它显示数字不会as以您想要的方式进行字符串化。

您可以尝试使用.ToString()

答案 1 :(得分:1)

好的,感谢@mcl建议调试一直向下(View> Controller> Model)到验证属性!

以下是发生的事情:当在文本框中插入无效输入绑定到模型中不是字符串的任何内容时,'DefaultModelBinder'将其值设置为'null',然后甚至到达控制器! (任何人都有更多信息吗?我会很高兴!)

答案 2 :(得分:1)

如果您的方案是您试图将验证器粘贴在int,decimal等类型的属性上,进入的值不能转换为int,decimal等那么这是故意的。

考虑一下你要求MVC框架做什么。该属性的类型为int,因此MVC框架使用int类型的值。 (从技术上讲,它正在使用类似于Nullable< int>的东西。)如果传入的值不能转换为int,则无法在Nullable< int>中表示它。除 null 之外,因为该类型不能包含任意字符串。这就是为什么验证属性最终将 null 作为值。

修改

如果要控制此错误消息,最简单的选项是将属性更改为字符串,然后让自定义验证程序调用Int32.TryParse或您需要执行的任何操作以验证用户键入的内容是什么数字。然后,您可以拥有一个单独的只读属性,该属性基本上是该属性值的数字形式。

更复杂但更通用,您可以使用自己的创建替换内置的DefaultModelBinder。在BindModel方法中,在ModelState中查找FormatException类型的异常,然后将其替换为您选择的错误消息。有关如何完成此操作的示例,请参见方法DefaultModelBinder.BindProperty的结尾。

答案 3 :(得分:0)

当我将自定义验证程序附加到由另一种类型的私有变量支持的属性时,我遇到了同样的问题。例如:

    private DateTime _dt;

    [LocalizedValidDateAttribute("Resources.DateTimeOffsetModel.App_GlobalResources", "TimePart_Invalid")]   
    public string DateTimeString
    {
        get { return _dt.ToString(); }
        set { DateTime.TryParse(value, out _dt); }
    }    

如果你传递DateTimeString =“foobar”;当LocalizedValidDateAttribute.IsValid()触发时,它将尝试获取DateTimeString的值,该值将为null,因为“foobar”不是字符串。

希望这可以帮助其他人,除了我花了2个小时才弄明白。