ASP.NET MVC3 中使用IValidatableObject接口实现Model数据验证

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这个方法。

03public class Product:IValidatableObject
04    {
05        /// <summary>
06        /// 产品名称
07        /// </summary>
08        [DisplayName("产品名称")]
09        [AllowHtml]//允许输入html脚本
10        [Required]
11        public String Name { get; set; }
12        /// <summary>
13        /// 库存数量
14        /// </summary>
15        [DisplayName("库存")]
16        [Required]
17        public int Inventory { get; set; }
18  
19        /// <summary>
20        /// 销售数量
21        /// </summary>
22        [DisplayName("售出")]
23        [Required]
24        public int Shipping { get; set; }
25  
26  
27        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
28        {
29              
30            if (Shipping > Inventory)
31            {
32                yield return new ValidationResult("出库数量不能大于库存数量", new string[] { "Shipping" });
33            }
34        }
35  
36          
37          
38    }


 

Index.cshtml

 

 

03@model 数据验证.Product
04  
05@{
06    Layout = null;
07}
08  
09<!DOCTYPE html>
10  
11<html>
12<head>
13    <title>Index</title>
14</head>
15<body>
16    <script src="http://www.cnblogs.com/Scripts/jquery-1.4.4.min.js" type="text/javascript"></script>
17    <script src="http://www.cnblogs.com/Scripts/jquery.validate.min.js" type="text/javascript"></script>
18    <script src="http://www.cnblogs.com/Scripts/jquery.validate.unobtrusive.min.js" type="text/javascript"></script>
19      
20    @using (Html.BeginForm()) {
21        @Html.ValidationSummary(true)
22        <fieldset>
23            <legend>Product</legend>
24      
25            <div class="editor-label">
26                @Html.LabelFor(model => model.Name)
27            </div>
28            <div class="editor-field">
29                @Html.EditorFor(model => model.Name)
30                @Html.ValidationMessageFor(model => model.Name)
31            </div>
32      
33            <div class="editor-label">
34                @Html.LabelFor(model => model.Inventory)
35            </div>
36            <div class="editor-field">
37                @Html.EditorFor(model => model.Inventory)
38                @Html.ValidationMessageFor(model => model.Inventory)
39            </div>
40      
41            <div class="editor-label">
42                @Html.LabelFor(model => model.Shipping)
43            </div>
44            <div class="editor-field">
45                @Html.EditorFor(model => model.Shipping)
46                @Html.ValidationMessageFor(model => model.Shipping)
47            </div>
48      
49            <p>
50                <input type="submit" value="Create" />
51            </p>
52        </fieldset>
53    }
54      
55    <div>
56        @Html.ActionLink("Back to List", "Index")
57    </div>
58      
59</body>
60</html>

 


当我们输入出库的数量大于库存的数量时,那么我们会得到错误提示,OK搞定了。

但是还有一个小问题,Validate方法中定义的错误提示,两个属性的名称是我们硬编码的,不利于我们的维护,试想假如有一天我们将Inventory和Shipping的Display属性分别改成别的名称,那么我们原来的错误提示”出库数量不能大于库存数量”就不太恰当了,为了解决这个问题,我们可以使用反射来获取这两个属性的DisplayName值,上代码:

EntityAttribute.cs

03public class EntityAttribute
04    {
05        private Type type;
06        public EntityAttribute(Type type)
07        {
08            this.type = type;
09        }
10        public string GetDisplayAttributeName(string propertyName)
11        {
12            var propertyInfo = type.GetProperty(propertyName);
13            object[] attrs = propertyInfo.GetCustomAttributes(typeof(DisplayNameAttribute), true);
14            return (attrs[0] as DisplayNameAttribute).DisplayName;
15        }
16    }
这个EntityAttribute.cs类可以返回指定模型类的指定属性的DisplayName值。

然后我们在更新我们的Product.cs代码

 

03public class Product:IValidatableObject
04    {
05        /// <summary>
06        /// 产品名称
07        /// </summary>
08        [DisplayName("产品名称")]
09        [AllowHtml]//允许输入html脚本
10        [Required]
11        public String Name { get; set; }
12        /// <summary>
13        /// 库存数量
14        /// </summary>
15        [DisplayName("库存")]
16        [Required]
17        public int Inventory { get; set; }
18  
19        /// <summary>
20        /// 销售数量
21        /// </summary>
22        [DisplayName("售出")]
23        [Required]
24        public int Shipping { get; set; }
25  
26  
27  
28        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
29        {
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)
36            {
37                yield return new ValidationResult(string.Format("{0}数量不能大于{1}数量", shippingDisplayName, inventoryDisplayName), new string[] { "Shipping" });
38            }
39        }
40            
41    }

这回终于大功告成了!

 

转:http://www.cnblogs.com/bjs007/archive/2011/01/27/1946419.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值