C#模型验证类的实现

 首先看一段代码

  public class TestController : BaseController
    {


        public ActionResult Create(Product product)
        {
            if (string.IsNullOrWhiteSpace(product.Name))  //判断商品名称是否为空
            {
                return Content("商品Name不可为空");
            }
            if (string.IsNullOrWhiteSpace(product.CategoryId)) //判断商品类别Id是否为空
            {
                return Content("商品CategoryId不可为空");
            }
            if (Service.BaseService.Query<Entity.Category>($"select *from dbo.[Category] where Id='{product.CategoryId}'").FirstOrDefault() == null) //判断商品类别Id是否为空
            {
                return Content("不存在的商品CategoryId");
            }


            //todo 判断完成,写入数据库



            return Content("添加成功");
        }

 

            在做后端验证时,我们经常会写到如上的代码,判断是否为空,判断是否符合格式,判断是否存在于数据库中,写多了难免使人烦躁。

  好在Net框架中出现了数据标注System.ComponentModel.DataAnnotations。   这是一个很棒的组件,但是用起来并不顺手,比如他不能验证单个值,支持的属性也比较少,实际使用中很多需要自己来实现。

所以接下来我们从头实现一个C#验证的插件,

 

实现中。。。。。

实现中。。。。。

实现中。。。。。

实现完成。

 

基本配置

首先定义一个验证类让所有需要的验证继承于此

 

    public abstract class ValidationAttribute : Attribute
    {
        public string ErrorMessage { get; set; }
        public string Name { get; set; }
        public virtual bool Verify(object o)
        {
            return false;
        }
    }

 

 

 

 

 1 using Common.EntityValidation;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Web;
 6 
 7 namespace TestMvc.Models
 8 {
 9     public class Student
10     {
11 
12         [NotNull(ErrorMessage = "Id是必须的")]    //验证非空,自定义ErroMessage
13         public string Id { get; set; }
14 
15 
16         [LengthAttribute(Max = 10, ErrorMessage = "个人介绍的长度")] //字符长度限制
17         public string Introduce { get; set; }  //个人介绍
18 
19 
20         [Range(Min =1,Max =120)]      //数值类型大小区间限制,最小,最大
21         public int Age { get; set; }
22 
23 
24         [Range( Min = "1900-10-10",Max = "2100-10-10")]   //字符类型的区间
25         public string Birthday { get; set;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          }
26 
27 
28         [Chinese]
29         public string Name { get; set; }  //只能是中文
30 
31 
32 
33         [In(Range = "高中生,初中生,小学生")]
34         public string StudentType { get; set; }//只能是  "高中生","初中生","小学生" 之一
35 
36 
37       
38 
39 
40 
41         [DbValidation(Sql = "select*from dbo.[data] where id=@ClassId")]  //数据库验证,验证班级Id  ClassId是否存在于数据库中
42         public string ClassId { get; set; }
43 
44 
45 
46         [Mobile]
47         public string CellPhone { get; set; }
48 
49 
50         [Email]
51 
52         public string Email { get; set; }
53 
54         [IdCard]
55         public string IdCard { get; set; }
56 
57 
58 
59         [InEnum(RangeType = typeof(StuState))]  //只能是属于枚举中的值 ,0 或者 2或者4
60         public int StuState { get; set; }
61     }
62 
63     public enum StuState
64     {
65 
66         上学中 = 0,
67         肄业 = 2,
68         退学 = 4,
69 
70 
71     }
72 }

 

 调用过程

using Common.EntityValidation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using TestMvc.Models;

namespace TestMvc.Controllers
{
    public class HomeController : Controller
    {
       

        public ActionResult Create(Student student)
        {

            #region
            var defaulVali = EntifyValidator.Validate(student);// 验证实体,默认验证所有字段
            #endregion



            #region
            var  IgnoreVali = EntifyValidator.Validate(student,"ClassId");// 验证实体,跳过字段ClassId的验证
            #endregion


            #region
            var r2 = EntifyValidator.ValidateQuickly(student);//快速验证,当有不通过的字段时,立即返回

            #endregion
            #region

            string pwd = Request["Pwd"];   

            var vPwd = StrongPassWordAttribute.IsValid(pwd); //验证单个value,验证是否强密码

            if (!vPwd.IsValid) 
            {

                return Content(vPwd.ErrorMessage);   //这不是一个强密码
            }

            #endregion


            if (defaulVali.IsValid)   //返回true或者false
            {

                return Content(defaulVali.ErrorMessage);
            }
            //TODO
            return Content("");
        }


    }


    //自定义
    public class CustomAttribute:ValidationAttribute
    {


        public override bool Verify(object o)
        {
            //这里写验证逻辑


            return false;
        }

    }
}

 

 

使用数据库验证时可以在应用程序入口初始化连接值

 

 

   

     protected void Application_Start()

        {

            AreaRegistration.RegisterAllAreas();

            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

            RouteConfig.RegisterRoutes(RouteTable.Routes);

            BundleConfig.RegisterBundles(BundleTable.Bundles);

 

            DbValidationAttribute.Init("server=XXXX;database=XX;user=sa;password=1234; pooling=true;max pool size=2048;");

 

 

 

 

自定义

 

    //自定义
    public class CustomAttribute:ValidationAttribute
    {


        public override bool Verify(object o)
        {
            //这里写验证逻辑


            return false;
        }

    }

 

 

 

验证的主要方法

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Common.EntityValidation
{
    public class EntifyValidator
    {
        public static ValidResult Validate(object data, params string[] ignore) //验证完所有字段
        {
            return new EntifyValidator().Verify(false, data, ignore);
           
        }
        public static ValidResult ValidateQuickly(object data, params string[] ignore)  //当有未通过的验证时,直接返回,停止验证
        {

            return   new EntifyValidator().Verify(true, data, ignore);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="quickly">验证完所有字段Or验证到未通过的立即返回</param>
        /// <param name="data">需要验证的数据</param>
        /// <param name="ignore">忽略的字段</param>
        /// <returns></returns>
        public virtual ValidResult Verify(bool quickly, object data, params string[] ignore)
        {


            ValidResult result = new ValidResult();

            List<PropertyInfo> props = data.GetType().GetProperties().Where(a => !ignore.Contains(a.Name.ToLower())).ToList();



            foreach (var item in props)
            {
                var validateattrs = item.GetCustomAttributes(typeof(ValidationAttribute));//

                var input = item.GetValue(data);

                foreach (var itemattr in validateattrs)
                {
                    var attr = ((ValidationAttribute)itemattr);
                    if (attr != null)
                    {
                        attr.Name = item.Name;
                        var isvalid = attr.Verify(input);

                        if (!isvalid)
                        {
                            ValidResultDetail validResultDetail = new ValidResultDetail();
                            validResultDetail.Name = item.Name;
                            validResultDetail.ErrorMessage = string.Format(attr.ErrorMessage, item.Name);
                            validResultDetail.IsValid = false;
                            result.ValidResultDetails.Add(validResultDetail);
                            if(quickly)
                            {
                                return result;
                            }
                        }
                    }
                }
            }

            return result;
        }
    }
}

 

 

 源码地址:https://gitee.com/unclescar/Validator

欢迎下载,讨论,联系作者 QQ 634892969

 

posted @ 2019-01-08 13:25  小小爵  阅读(3873)  评论(5编辑  收藏  举报