參數校驗的意義
在實際項目開發中,無論任何方式、任何規模的開發模式,項目中都離不開對接入數據模型參數的合法性校驗,目前普片的開發模式基本是前后端分離,當用戶在前端頁面中輸入一些表單數據時,點擊提交按鈕,觸發請求目標服務器的一系列后續操作,在這中間的執行過程中(標準做法推薦)無論是前端代碼部分,還是服務端代碼部分都應該有針對用戶輸入數據的合法性校驗,典型做法如下:
前端部分
:當用戶在頁面輸入表單數據時,前端監聽頁面表單事件觸發相應的數據合法性校驗規則,當數據非法時,合理的提示用戶數據錯誤,只有當所有表單數據都校驗通過后,才繼續提交數據給目標后端對應的接口;后端部分
:當前端數據合法校驗通過后,向目標服務器提交表單數據時,服務端接收到相應的提交數據,在入口源頭出就應該觸發相關的合法性校驗規則,當數據都校驗通過后,繼續執行后續的相關業務邏輯處理,反之則響應相關非法數據的提示信息;
特別說明:在實際的項目中,無論前端部分還是服務端部分,參數的校驗都是很有必要性的。無效的參數,可能會導致應用程序的異常和一些不可預知的錯誤行為。
常用的參數校驗項
這里例舉一些項目中比較常用的參數模型校驗項,如下所示:
Name:姓名校驗,比如需要是純漢字的姓名;
Password:密碼強度驗證,比如要求用戶輸入必須包含大小寫字母、數字和特殊符號的強密碼;
QQ:QQ 號碼驗證,是否是有效合法的 QQ 號碼;
China Postal Code:中國郵政編碼;
IP Address:IPV4 或者 IPV6 地址驗證;
Phone:手機號碼或者座機號碼合法性驗證;
ID Card:身份證號碼驗證,比如:15 位和 18 位數身份證號碼;
Email Address:郵箱地址的合法性校驗;
String:字符串驗證,比如字段是否不為 null、長度是否超限;
URL:驗證屬性是否具有 URL 格式;
Number:數值型參數校驗,數值范圍校驗,比如非負數,非負整數,正整數等;
File:文件路徑及擴展名校驗;
對于參數校驗,常見的方式有正則匹配校驗,通過對目標參數編寫合法的正則表達式,實現對參數合法性的校驗。
.NET 中內置 DataAnnotations 提供的特性校驗
上面我們介紹了一些常用的參數驗證項,接下來我們來了解下在 .NET
中內置提供的 DataAnnotations
數據注解,該類提供了一些常用的驗證參數特性。
官方解釋:
提供用于為
ASP.NET MVC
和ASP.NET
數據控件定義元數據的特性類。該類位于
System.ComponentModel.DataAnnotations
命名空間。
關于 DataAnnotations 中的特性介紹
讓我們可以通過這些特性對 API
請求中的參數進行驗證,常用的特性一般有:
**[ValidateNever]**:指示應從驗證中排除屬性或參數。
**[CreditCard]**:驗證屬性是否具有信用卡格式。
**[Compare]**:驗證模型中的兩個屬性是否匹配。
**[EmailAddress]**:驗證屬性是否具有電子郵件格式。
**[Phone]**:驗證屬性是否具有電話號碼格式。
**[Range]**:驗證屬性值是否位于指定范圍內。
**[RegularExpression]**:驗證屬性值是否與指定的正則表達式匹配。
**[Required]**:驗證字段是否不為 null。
**[StringLength]**:驗證字符串屬性值是否不超過指定的長度限制。
**[Url]**:驗證屬性是否具有 URL 格式。
其中 RegularExpression
特性,基于正則表達式可以擴展實現很多常用的驗證類型,下面的( 基于 DataAnnotations 的通用模型校驗封裝
)環節舉例說明。
關于該類更多詳細信息請查看,
https://learn.microsoft.com/zh-cn/dotnet/api/system.componentmodel.dataannotations?view=net-7.0
基于 DataAnnotations 的通用模型校驗封裝
此處主要是使用了 Validator.TryValidateObject()
方法:
Validator.TryValidateObject(object?instance,?ValidationContext?validationContext,?ICollection<ValidationResult>??validationResults,?bool?validateAllProperties);
Validator
類提供如下校驗方法:

基于 DataAnnotations 的特性校驗助手實現步驟
錯誤成員對象類
ErrorMember
namespace?Jeff.Common.Validatetion;///?<summary>
///?錯誤成員對象
///?</summary>
public?class?ErrorMember
{///?<summary>///?錯誤信息///?</summary>public?string??ErrorMessage?{?get;?set;?}///?<summary>///?錯誤成員名稱///?</summary>public?string??ErrorMemberName?{?get;?set;?}
}
驗證結果類
ValidResult
namespace?Jeff.Common.Validatetion;///?<summary>
///?驗證結果類
///?</summary>
public?class?ValidResult
{public?ValidResult(){ErrorMembers?=?new?List<ErrorMember>();}///?<summary>///?錯誤成員列表///?</summary>public?List<ErrorMember>?ErrorMembers?{?get;?set;?}///?<summary>///?驗證結果///?</summary>public?bool?IsVaild?{?get;?set;?}
}
定義操作正則表達式的公共類
RegexHelper
(基于RegularExpression
特性擴展)
using?System;
using?System.Net;
using?System.Text.RegularExpressions;namespace?Jeff.Common.Validatetion;///?<summary>
///?操作正則表達式的公共類
///?Regex 用法參考:https://learn.microsoft.com/zh-cn/dotnet/api/system.text.regularexpressions.regex.-ctor?redirectedfrom=MSDN&view=net-7.0
///?</summary>???
public?class?RegexHelper
{#region?常用正則驗證模式字符串public?enum?ValidateType{Email,?????????????????//?郵箱TelePhoneNumber,???????//?固定電話(座機)MobilePhoneNumber,?????//?移動電話Age,???????????????????//?年齡(1-120?之間有效)Birthday,??????????????//?出生日期Timespan,??????????????//?時間戳IdentityCardNumber,????//?身份證IpV4,??????????????????//?IPv4?地址IpV6,??????????????????//?IPV6?地址Domain,????????????????//?域名English,???????????????//?英文字母Chinese,???????????????//?漢字MacAddress,????????????//?MAC?地址Url,???????????????????//?URL?}private?static?readonly?Dictionary<ValidateType,?string>?keyValuePairs?=?new?Dictionary<ValidateType,?string>{{?ValidateType.Email,?_Email?},{?ValidateType.TelePhoneNumber,_TelephoneNumber?},??{?ValidateType.MobilePhoneNumber,_MobilePhoneNumber?},?{?ValidateType.Age,_Age?},?{?ValidateType.Birthday,_Birthday?},?{?ValidateType.Timespan,_Timespan },?{?ValidateType.IdentityCardNumber,_IdentityCardNumber?},?{?ValidateType.IpV4,_IpV4?},?{?ValidateType.IpV6,_IpV6?},?{?ValidateType.Domain,_Domain?},?{?ValidateType.English,_English?},?{?ValidateType.Chinese,_Chinese?},?{?ValidateType.MacAddress,_MacAddress?},?{?ValidateType.Url,_Url?},?};public?const?string?_Email?=?@"^(\w)+(\.\w)*@(\w)+((\.\w+)+)$";?//?^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$?,?[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}public?const?string?_TelephoneNumber?=?@"(d+-)?(d{4}-?d{7}|d{3}-?d{8}|^d{7,8})(-d+)?";?//座機號碼(中國大陸)public?const?string?_MobilePhoneNumber?=?@"^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$";?//移動電話public?const?string?_Age?=?@"^(?:[1-9][0-9]?|1[01][0-9]|120)$";?//?年齡?1-120?之間有效public?const?string?_Birthday?=?@"^((?:19[2-9]\d{1})|(?:20(?:(?:0[0-9])|(?:1[0-8]))))((?:0?[1-9])|(?:1[0-2]))((?:0?[1-9])|(?:[1-2][0-9])|30|31)$";public?const?string?_Timespan =?@"^15|16|17\d{8,11}$";?//?目前時間戳是15開頭,以后16、17等開頭,長度 10?位是秒級時間戳的正則,13 位時間戳是到毫秒級的。public?const?string?_IdentityCardNumber?=?@"^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$";public?const?string?_IpV4?=?@"^((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}$";public?const?string?_IpV6?=?@"^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$";public?const?string?_Domain?=?@"^[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?$";public?const?string?_English?=?@"^[A-Za-z]+$";public?const?string?_Chinese?=?@"^[\u4e00-\u9fa5]{0,}$";public?const?string?_MacAddress?=?@"^([0-9A-F]{2})(-[0-9A-F]{2}){5}$";public?const?string?_Url?=?@"^[a-zA-z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\S*)?$";#endregion///?<summary>///?獲取驗證模式字符串///?</summary>///?<param?name="validateType"></param>///?<returns></returns>public?static?(bool?hasPattern,?string?pattern)?GetValidatePattern(ValidateType?validateType)?{bool?hasPattern?=?keyValuePairs.TryGetValue(validateType,?out?string??pattern);return?(hasPattern,?pattern????string.Empty);}#region?驗證輸入字符串是否與模式字符串匹配///?<summary>///?驗證輸入字符串是否與模式字符串匹配///?</summary>///?<param?name="input">輸入的字符串</param>///?<param?name="validateType">模式字符串類型</param>///?<param?name="matchTimeout">超時間隔</param>///?<param?name="options">篩選條件</param>///?<returns></returns>public?static?(bool?isMatch,?string?info)?IsMatch(string?input,?ValidateType?validateType,?TimeSpan?matchTimeout,?RegexOptions?options?=?RegexOptions.None){var?(hasPattern,?pattern)?=?GetValidatePattern(validateType);if?(hasPattern?&&?!string.IsNullOrWhiteSpace(pattern)){bool?isMatch?=?IsMatch(input,?pattern,?matchTimeout,?options);if?(isMatch)?return?(true,?"Format?validation?passed.");?//?格式驗證通過。else?return?(false,?"Format?validation?failed.");?//?格式驗證未通過。}return?(false,?"Unknown?ValidatePattern.");?//?未知驗證模式}///?<summary>///?驗證輸入字符串是否與模式字符串匹配,匹配返回true///?</summary>///?<param?name="input">輸入字符串</param>///?<param?name="pattern">模式字符串</param>????///?<returns></returns>public?static?bool?IsMatch(string?input,?string?pattern){return?IsMatch(input,?pattern,?TimeSpan.Zero,?RegexOptions.IgnoreCase);}///?<summary>///?驗證輸入字符串是否與模式字符串匹配,匹配返回true///?</summary>///?<param?name="input">輸入的字符串</param>///?<param?name="pattern">模式字符串</param>///?<param?name="matchTimeout">超時間隔</param>///?<param?name="options">篩選條件</param>///?<returns></returns>public?static?bool?IsMatch(string?input,?string?pattern,?TimeSpan?matchTimeout,?RegexOptions?options?=?RegexOptions.None){return?Regex.IsMatch(input,?pattern,?options,?matchTimeout);}#endregion
}
定義驗證結果統一模型格式類
ResponseInfo
(此類通常也是通用的數據響應模型類)
namespace?Jeff.Common.Model;public?sealed?class?ResponseInfo<T>?where?T?:?class
{/*Microsoft.AspNetCore.Http.StatusCodesSystem.Net.HttpStatusCode*////?<summary>///?響應代碼(自定義)///?</summary>public?int?Code?{?get;?set;?}///?<summary>///?接口狀態///?</summary>public?bool?Success?{?get;?set;?}#region?此處可以考慮多語言國際化設計(語言提示代號對照表)///?<summary>///?語言對照碼,參考:https://blog.csdn.net/shenenhua/article/details/79150053///?</summary>public?string?Lang?{?get;?set;?}?=?"zh-cn";///?<summary>///?提示信息///?</summary>public?string?Message?{?get;?set;?}?=?string.Empty;#endregion///?<summary>///?數據體///?</summary>public?T??Data?{?get;?set;?}
}
實現驗證助手類
ValidatetionHelper
,配合System.ComponentModel.DataAnnotations
類使用
//?數據注解,https://learn.microsoft.com/zh-cn/dotnet/api/system.componentmodel.dataannotations?view=net-7.0
using?System.ComponentModel.DataAnnotations;
using?Jeff.Common.Model;namespace?Jeff.Common.Validatetion;///?<summary>
///?驗證助手類
///?</summary>
public?sealed?class?ValidatetionHelper
{///?<summary>///?DTO?模型校驗///?</summary>///?<param?name="value"></param>///?<returns></returns>public?static?ValidResult?IsValid(object?value){var?result?=?new?ValidResult();try{var?validationContext?=?new?ValidationContext(value);var?results?=?new?List<ValidationResult>();bool?isValid?=?Validator.TryValidateObject(value,?validationContext,?results,?true);result.IsVaild?=?isValid;if?(!isValid){foreach?(ValidationResult??item?in?results){result.ErrorMembers.Add(new?ErrorMember(){ErrorMessage?=?item.ErrorMessage,ErrorMemberName?=?item.MemberNames.FirstOrDefault()});}}}catch?(ValidationException?ex){result.IsVaild?=?false;result.ErrorMembers?=?new?List<ErrorMember>{new?ErrorMember(){ErrorMessage?=?ex.Message,ErrorMemberName?=?"Internal?error"}};}return?result;}///?<summary>///?DTO?模型校驗統一響應信息///?</summary>///?<typeparam?name="T"></typeparam>///?<param?name="model"></param>///?<returns></returns>public?static?ResponseInfo<ValidResult>?GetValidInfo<T>(T?model)?where?T?:?class{var?result?=?new?ResponseInfo<ValidResult>();var?validResult?=?IsValid(model);if?(!validResult.IsVaild){result.Code?=?420;result.Message?=?"DTO?模型參數值異常";result.Success?=?false;result.Data?=?validResult;}else{result.Code?=?200;result.Success?=?true;result.Message?=?"DTO?模型參數值合法";}return?result;}
}
如何使用 DataAnnotations 封裝的特性校驗助手?
首先定義一個數據模型類(
DTO
),添加校驗特性ValidationAttribute
using?System.ComponentModel.DataAnnotations;
using?Jeff.Common.Validatetion;namespace?Jeff.Comm.Test;public?class?Person
{[Display(Name?=?"姓名"),?Required(ErrorMessage?=?"{0}必須填寫")]public?string?Name?{?get;?set;?}[Display(Name?=?"郵箱")][Required(ErrorMessage?=?"{0}必須填寫")][RegularExpression(RegexHelper._Email,?ErrorMessage?=?"RegularExpression:?{0}格式非法")][EmailAddress(ErrorMessage?=?"EmailAddress:?{0}格式非法")]public?string?Email?{?get;?set;?}[Display(Name?=?"Age年齡")][Required(ErrorMessage?=?"{0}必須填寫")][Range(1,?120,?ErrorMessage?=?"超出范圍")][RegularExpression(RegexHelper._Age,?ErrorMessage?=?"{0}超出合理范圍")]public?int?Age?{?get;?set;?}[Display(Name?=?"Birthday出生日期")][Required(ErrorMessage?=?"{0}必須填寫")][RegularExpression(RegexHelper._Timespan,?ErrorMessage?=?"{0}超出合理范圍")]public?TimeSpan?Birthday?{?get;?set;?}[Display(Name?=?"Address住址")][Required(ErrorMessage?=?"{0}必須填寫")][StringLength(200,?MinimumLength?=?10,?ErrorMessage?=?"{0}輸入長度不正確")]public?string?Address?{?get;?set;?}[Display(Name?=?"Mobile手機號碼")][Required(ErrorMessage?=?"{0}必須填寫")][RegularExpression(RegexHelper._MobilePhoneNumber,?ErrorMessage?=?"{0}格式非法")]public?string?Mobile?{?get;?set;?}[Display(Name?=?"Salary薪水")][Required(ErrorMessage?=?"{0}必須填寫")][Range(typeof(decimal),?"1000.00",?"3000.99")]public?decimal?Salary?{?get;?set;?}[Display(Name?=?"MyUrl連接")][Required(ErrorMessage?=?"{0}必須填寫")][Url(ErrorMessage?=?"Url:{0}格式非法")][RegularExpression(RegexHelper._Url,?ErrorMessage?=?"RegularExpression:{0}格式非法")]public?string?MyUrl?{?get;?set;?}
}
控制臺調用通用校驗助手驗證方法
ValidatetionHelper.IsValid()
或ValidatetionHelper.GetValidInfo()
//?通用模型數據驗證測試
static?void?ValidatetionTest()?
{var?p?=?new?Person{Name?=?"",Age?=?-10,Email?=?"www.baidu.com",MobilePhoneNumber?=?"12345",Salary?=?4000,MyUrl?=?"aaa"};//?調用通用模型校驗var?result?=?ValidatetionHelper.IsValid(p);if?(!result.IsVaild){foreach?(ErrorMember?errorMember?in?result.ErrorMembers){//?控制臺打印字段驗證信息Console.WriteLine($"{errorMember.ErrorMemberName}:{errorMember.ErrorMessage}");}}Console.WriteLine();//?調用通用模型校驗,返回統一數據格式var?validInfo?=?ValidatetionHelper.GetValidInfo(p);var?options?=?new?JsonSerializerOptions{Encoder?=?JavaScriptEncoder.UnsafeRelaxedJsonEscaping,?//?設置中文編碼亂碼WriteIndented?=?false};string?jsonStr?=?JsonSerializer.Serialize(validInfo,?options);Console.WriteLine($"校驗結果返回統一數據格式:{jsonStr}");
}
在控制臺Program.Main
方法中調用 ValidatetionTest()
方法:
internal?class?Program
{static?void?Main(string[]?args){Console.WriteLine("Hello,?DataAnnotations!");{#region?數據注解(DataAnnotations)模型驗證ValidatetionTest();?#endregion}Console.ReadKey();}
啟動控制臺,輸出如下信息:
如何實現自定義的驗證特性?
當我們碰到這些參數需要驗證的時候,而上面內置類提供的特性又不能滿足需求時,此時我們可以實現自定義的驗證特性來滿足校驗需求,按照微軟給出的編碼規則,我們只需繼承 ValidationAttribute
類,并重寫 IsValid()
方法即可。
自定義校驗特性案例
比如實現一個密碼強度的驗證,實現步驟如下:
定義密碼強度規則,只包含英文字母、數字和特殊字符的組合,并且組合長度至少 8 位數;
///?<summary>
///?只包含英文字母、數字和特殊字符的組合
///?</summary>
///?<returns></returns>
public?static?bool?IsCombinationOfEnglishNumberSymbol(string?input,?int??minLength?=?null,?int??maxLength?=?null)
{var?pattern?=?@"(?=.*\d)(?=.*[a-zA-Z])(?=.*[^a-zA-Z\d]).";if?(minLength?is?null?&&?maxLength?is?null)pattern?=?$@"^{pattern}+$";else?if?(minLength?is?not?null?&&?maxLength?is?null)pattern?=?$@"^{pattern}{{{minLength},}}$";else?if?(minLength?is?null?&&?maxLength?is?not?null)pattern?=?$@"^{pattern}{{1,{maxLength}}}$";elsepattern?=?$@"^{pattern}{{{minLength},{maxLength}}}$";return?Regex.IsMatch(input,?pattern);
}
實現自定義特性
EnglishNumberSymbolCombinationAttribute
,繼承自ValidationAttribute
;
using?System.ComponentModel.DataAnnotations;namespace?Jeff.Common.Validatetion.CustomAttributes;///?<summary>
///?是否是英文字母、數字和特殊字符的組合
///?</summary>
public?class?EnglishNumberSymbolCombinationAttribute?:?ValidationAttribute
{///?<summary>///?默認的錯誤提示信息///?</summary>private?const?string?error?=?"無效的英文字母、數字和特殊字符的組合";protected?override?ValidationResult?IsValid(object?value,?ValidationContext?validationContext){if?(value?is?null)?return?new?ValidationResult("參數值為?null");//if?(value?is?null)//{//????throw?new?ArgumentNullException(nameof(attribute));//}//?驗證參數邏輯?value?是需要驗證的值,而?validationContext?中包含了驗證相關的上下文信息,這里可自己封裝一個驗證格式的?FormatValidation?類if?(FormatValidation.IsCombinationOfEnglishNumberSymbol(value?as?string,?8))//驗證成功返回?successreturn?ValidationResult.Success;//不成功?提示驗證錯誤的信息else?return?new?ValidationResult(ErrorMessage????error);}
}
以上就實現了一個自定義規則的 自定義驗證特性
,使用方式很簡單,可以把它附屬在我們 請求的參數
上或者 DTO 里的屬性
,也可以是 Action 上的形參
,如下所示:
public?class?CreateDTO
{[Required]public?string?StoreName?{?get;?init;?}[Required]//?附屬在?DTO?里的屬性[EnglishNumberSymbolCombination(ErrorMessage?=?"UserId?必須是英文字母、數字和特殊符號的組合")]public?string?UserId?{?get;?init;?}
}
...
//?附屬在?Action?上的形參
[HttpGet]
public?async?ValueTask<ActionResult>?Delete([EnglishNumberSymbolCombination]string?userId,?string?storeName)
該自定義驗證特性還可以結合 DataAnnotations
內置的 [Compare]
特性,可以實現賬號注冊的密碼確認驗證(輸入密碼和確認密碼是否一致性
)。關于更多自定義參數校驗特性,感興趣的小伙伴可參照上面案例的實現思路,自行擴展實現喲。
總結
對于模型參數的校驗,在實際項目系統中是非常有必要性的(通常在數據源頭提供驗證),利用 .NET
內置的 DataAnnotations
(數據注解)提供的特性校驗,可以很方便的實現通用的模型校驗助手,關于其他特性的用法,請自行參考微軟官方文檔,這里注意下RegularExpressionAttribute
(指定 ASP.NET
動態數據中的數據字段值必須與指定的正則表達式匹配),該特性可以方便的接入正則匹配驗證,當遇到復雜的參數校驗時,可以快速方便的擴展自定義校驗特性,從此告別傳統編碼中各種 if(xxx != yyyy)
判斷的驗證,讓整體代碼編寫更佳簡練干凈。