首先看一段代碼git
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#驗證的插件,框架
實現中。。。。。ide
實現中。。。。。ui
實現中。。。。。spa
實現完成。插件
基本配置code
首先定義一個驗證類讓全部須要的驗證繼承於此orm
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