ValidationAttribute 的值始终为 null
这是我编写的一个简单的验证属性,用于强制执行仅限数字的字符串(我用它来验证电话号码、邮政编码等):
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;
}
}
问题是,当用于验证除字符串之外的其他字符串时,例如小数、短整型、整数或任何其他值否则,对象值
始终为null
。为什么只验证数字小数?因为如果不这样做,我会收到默认验证消息“值‘x’对于‘propertyName’无效”。我知道默认验证消息的特定问题的解决方案。
我只是想了解为什么它总是为空...
顺便说一句,我正在使用 VS2008、ASP.NET MVC 2(最终版)、.NET 3.5 SP1。
Here's a simple validation attribute I wrote to enforce number-only strings (I use it to validate phone numbers, postal codes and alike):
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;
}
}
The problem is that when used to validate other than strings, let's say a decimal, short, int or anything else, object value
is ALWAYS null
. Why validate numeric only decimals? Because if I don't, I get the default validation message 'The value 'x' is not valid for 'propertyName'. I'm aware of the solutions for the specific problem of the default validation message.
I just want to understand WHY it's always null...
BTW, I'm using VS2008, ASP.NET MVC 2 (final), .NET 3.5 SP1.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您确定
value
为 null 而不仅仅是stringValue
吗?MSDN 上关于
as
运算符的说法是这样的:http://msdn.microsoft.com/en-us /library/cscsdfbt%28VS.71%29.aspx
在该页面上的示例中,它表明数字并不按照您想要的方式
as
到字符串。您可以尝试
.ToString()
。Are you positive it is
value
that is null and not juststringValue
?So sayeth the MSDN about your
as
operator:http://msdn.microsoft.com/en-us/library/cscsdfbt%28VS.71%29.aspx
In the examples on that page it shows that numerics do not
as
to strings the way you want.You might try
.ToString()
instead.好的,感谢 @mcl 建议一路调试(视图 > 控制器 > 模型)到验证属性!
发生的事情是这样的:当在绑定到模型中任何非字符串的文本框中插入无效输入时,“DefaultModelBinder”将其值设置为“null”在到达控制器之前! (有人有更多相关信息吗?我会很高兴!)
Ok, thanks @mcl for suggesting debugging all the way down (View > Controller > Model) to the validation attribute!
Here's what happened: when inserting invalid input in a textbox binded to anything that's not a string in the model, the ´DefaultModelBinder´ sets it's value to ´null´ before it reaches even the controller! (Anyone have more info on that? I would be glad!)
如果您的场景是尝试将验证器固定在 int、decimal 等类型的属性上,并且传入的值不能转换为 int、decimal 等,那么这是故意的。
考虑一下您要求 MVC 框架做什么。该属性的类型为 int,因此 MVC 框架使用 int 类型的值。 (从技术上讲,它使用更类似于 Nullable的东西。)如果传入值不可转换为 int,则无法在 Nullable中表示它。除了 null 之外,因为该类型不能包含任意字符串。这就是为什么您的验证属性最终得到 null 作为值。
编辑:
如果您想控制此错误消息,最简单的选择是将属性更改为字符串,然后让您的自定义验证器调用 Int32.TryParse 或您需要它执行的任何操作以进行验证用户输入的内容是数字。然后,您可以拥有一个单独的只读属性,它基本上是该属性值的数字形式。
更复杂但更通用,您可以用您自己的创建之一替换内置的 DefaultModelBinder。在 BindModel 方法中,在 ModelState 中查找 FormatException 类型的异常,然后将其替换为您选择的错误消息。有关如何完成此操作的示例,请参阅方法 DefaultModelBinder.BindProperty 的末尾。
If your scenario is that you're trying to stick your validator on a property of type int, decimal, etc., and the value coming in isn't convertible to int, decimal, etc., then this is intentional.
Consider what you're asking the MVC framework to do. The property is of type int, so the MVC framework is working with values of type int. (Technically, it's working with something more akin to Nullable<int>.) If the incoming value isn't convertible to int, there's no way to represent that in a Nullable<int> other than null since that type can't contain arbitrary strings. So that's why your validation attribute ends up getting null as a value.
Edit:
If you want to control this error message, the easiest option is to change the property to a string, then have your custom validator call Int32.TryParse or whatever you need it to do in order to verify that what the user typed is numeric. Then you can have a separate read-only property that's basically the numeric form of that property's value.
More complex but more generalized, you could replace the built-in DefaultModelBinder with one of your own creation. From within the BindModel method, look for exceptions of type FormatException in ModelState, then replace them with the error message of your choosing. See the end of the method DefaultModelBinder.BindProperty for an example of how this is done.
当我将自定义验证器附加到由另一种类型的私有变量支持的属性时,我遇到了同样的问题。例如:
如果您传递 DateTimeString = "foobar";当 LocalizedValidDateAttribute.IsValid() 触发时,它将尝试获取 DateTimeString 的值,该值将为 null,因为“foobar”不是字符串。
希望这能帮助其他人节省我花了两个小时才弄清楚的时间。
I had the same problem when I was attaching the custom validator to a property that was backed by a private variable of another type. For example:
If you pass DateTimeString = "foobar"; When LocalizedValidDateAttribute.IsValid() fires it's going to try to get the value of DateTimeString, which will be null because "foobar" is not a string.
Hopefully this will help someone else out there save the 2 hours it took me to figure it out.
一旦您还可以检查您放置验证属性的字段,
例如:
Once You can also check the field on which u put the validation Attribute
ex: