ASP.NET MVC3 中使用IValidatableObject接口实现Model数据验证
此接口弥补了MVC2中的数据验证脱离DB的不足。
==============================================================
ASP.NET MVC3新增了许多新特性,IValidatableObject接口就是新增的诸多特性之一。ASPNET MBC3该书中是这样描述的:IValidatableObject 接口允许执行 Model 水平的验证,并且允许你提供整个模型状态的验证错误信息,或者基于 Model 的两个属性。当 Model 绑定的时候,MVC3 从 IValidatableObject 接收错误信息,在视图中使用内建的 HTML 助手时,将会自动标识或者高亮受影响的字段。
可能有人会问了,Mvc2中可以使用自定义验证来对模型进行验证,为什么mvc3中又新增了IValidatableObject这个借口呢?
不错,我们是可以通过继承ValidationAttribute类并且重写它的IsValid方法来自定义验证,但是这中做法有个局限性,那就是如果我需要验证模型的各个属性之间的逻辑关系,例如:我们有一个商品模型,我们要求这个模型的出库数量不能大于库存数量,那么自定义验证就显得不是那么给力了,这时候我们就需要ValidationAttribute接口了。
首先我们这个商品模型Product.cs需要实现ValidationAttribute接口,然后实现Validate这个方法。
03 | public class Product:IValidatableObject |
11 | public String Name { get ; set ; } |
17 | public int Inventory { get ; set ; } |
24 | public int Shipping { get ; set ; } |
27 | public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) |
30 | if (Shipping > Inventory) |
32 | yield return new ValidationResult( "出库数量不能大于库存数量" , new string [] { "Shipping" }); |
Index.cshtml
20 | @ using (Html.BeginForm()) { |
21 | @Html.ValidationSummary( true ) |
23 | <legend>Product</legend> |
25 | <div class = "editor-label" > |
26 | @Html.LabelFor(model => model.Name) |
28 | <div class = "editor-field" > |
29 | @Html.EditorFor(model => model.Name) |
30 | @Html.ValidationMessageFor(model => model.Name) |
33 | <div class = "editor-label" > |
34 | @Html.LabelFor(model => model.Inventory) |
36 | <div class = "editor-field" > |
37 | @Html.EditorFor(model => model.Inventory) |
38 | @Html.ValidationMessageFor(model => model.Inventory) |
41 | <div class = "editor-label" > |
42 | @Html.LabelFor(model => model.Shipping) |
44 | <div class = "editor-field" > |
45 | @Html.EditorFor(model => model.Shipping) |
46 | @Html.ValidationMessageFor(model => model.Shipping) |
50 | <input type= "submit" value= "Create" /> |
56 | @Html.ActionLink( "Back to List" , "Index" ) |
当我们输入出库的数量大于库存的数量时,那么我们会得到错误提示,OK搞定了。
但是还有一个小问题,Validate方法中定义的错误提示,两个属性的名称是我们硬编码的,不利于我们的维护,试想假如有一天我们将Inventory和Shipping的Display属性分别改成别的名称,那么我们原来的错误提示”出库数量不能大于库存数量”就不太恰当了,为了解决这个问题,我们可以使用反射来获取这两个属性的DisplayName值,上代码:
EntityAttribute.cs
03 | public class EntityAttribute |
06 | public EntityAttribute(Type type) |
10 | public string GetDisplayAttributeName( string propertyName) |
12 | var propertyInfo = type.GetProperty(propertyName); |
13 | object [] attrs = propertyInfo.GetCustomAttributes( typeof (DisplayNameAttribute), true ); |
14 | return (attrs[0] as DisplayNameAttribute).DisplayName; |
这个EntityAttribute.cs类可以返回指定模型类的指定属性的DisplayName值。
然后我们在更新我们的Product.cs代码
03 | public class Product:IValidatableObject |
11 | public String Name { get ; set ; } |
17 | public int Inventory { get ; set ; } |
24 | public int Shipping { get ; set ; } |
28 | public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) |
30 | Type type = typeof (Product); |
31 | EntityAttribute entityAttribute= new EntityAttribute(type); |
32 | PropertyInfo[] PropertyInfos= type.GetProperties(); |
33 | string shippingDisplayName = entityAttribute.GetDisplayAttributeName( "Shipping" ); |
34 | string inventoryDisplayName = entityAttribute.GetDisplayAttributeName( "Inventory" ); |
35 | if (Shipping > Inventory) |
37 | yield return new ValidationResult( string .Format( "{0}数量不能大于{1}数量" , shippingDisplayName, inventoryDisplayName), new string [] { "Shipping" }); |
这回终于大功告成了!
转:http://www.cnblogs.com/bjs007/archive/2011/01/27/1946419.html