Use Attribute to check whether the object property data is valid.
I. Preface
To put it bluntly, ASP. NET has only recently had the opportunity to use MVC to develop and produce projects. There are a large number of server-side data format validation for new and edited form submissions in the project. if else code is too cumbersome, especially when there are many forms of data, just today, I wrote a Demo to verify the data format in the Model layer. Here, we will explain that the MVC built-in data verification function can also proactively notify the front-end display, which is not very useful for the individual (not to be studied in depth ), in addition, the company's project does not use the MVC auxiliary method to generate a View, and it does not know whether the MVC data verification function can work.
Ii. Objectives
By calling the Validate method of the object, check whether all the attributes of the object are valid. Otherwise, a failure message is returned.
Iii. File structure
IV. Implementation
1. Because not all models should have the Validate method, and the logic code of the Validate method is also unique (parsing the features of object attributes, check whether the data is valid according to the rules described in the feature. Therefore, define the IValidate interface and bind the extended method Validate to IValidate, the Model to be verified inherits from the IValidate interface (the feature definition code used for data parsing is later)
Public interface IValidate {}View Codepublic static class ValidateExtension {// <summary> // check whether the object property value is valid /// </summary> /// <param name = "obj"> to be verified object </param> /// <returns> </returns> public static ValidateResult Validate (this IValidate obj) {ValidateResult result = new ValidateResult (); PropertyInfo [] infos = obj. getType (). getProperties (BindingFlags. public | BindingFlags. instance); foreach (PropertyInfo p in infos) {// obtain the data verification feature. Attribute [] attrs = Attribute. getCustomAttributes (p, typeof (ValidateAttribute), false); if (attrs. length <= 0) {continue;} // obtain the Name Description feature CaptionAttribute caption = Attribute. getCustomAttribute (p, typeof (CaptionAttribute), false) as CaptionAttribute; object value = p. getValue (obj); foreach (Attribute attr in attrs) {ValidateAttribute validate = attr as ValidateAttribute; if (validate = null) {con Tinue;} result = Validate (validate, value, caption); if (! Result. isSuccess) {return result ;}} return result ;} /// <summary> /// check whether the data is valid /// </summary> /// <param name = "validate"> check rules </param> /// <param name = "value"> value to be verified </param> // <param name = "caption"> description </param> /// <returns> </returns> static ValidateResult Validate (ValidateAttribute validate, object value, CaptionAttribute caption) {ValidateResult result = new ValidateResult (); if (! Validate. validate (value) {result. isSuccess = false; if (caption = null) {result. errorMessage = validate. getErrorMessage ();} else {result. errorMessage = validate. getErrorMessage (caption. name) ;}} return result ;}}View Code
2. Define features. First, we need a feature CaptionAttribute that describes the attribute name to describe the attribute name so that the Data Exception prompt is more friendly.
[AttributeUsage (AttributeTargets. property)] public class CaptionAttribute: attribute {// <summary> /// constructor // </summary> /// <param name = "name"> Attribute name </param> public CaptionAttribute (string name) {this. name = name ;}/// <summary> /// attribute Name /// </summary> public string Name {get; set ;}}View Code
3. Define features. Check whether the current rule can pass the same rule by using the Validate method, at the same time, when parsing rules, we should read attribute features only for verification-related features, rather than all. Therefore, the ValidateAttribute of the parent class of the feature is defined.
[AttributeUsage (AttributeTargets. property, Inherited = true)] public abstract class ValidateAttribute: attribute {// <summary> /// message displayed when the verification fails /// </summary> protected string ErrorMessage {get; set ;} /// <summary> /// check whether the data is valid /// </summary> /// <param name = "value"> value to be verified </param>/ // <returns> </returns> public abstract bool Validate (object value ); /// <summary> /// obtain the information indicating that the verification fails. /// </summary> /// <param name = "name"> Field name </param>/ // <returns> </returns> public string GetErrorMessage (string name = "") {if (string. isNullOrEmpty (name) {name = "this field";} return string. format (this. errorMessage, name );}}View Code
4. Define features and create relevant business rule features. In order to customize the prompt information during use, the constructor method should be reloaded (value range rules and regular expression verification rules are provided here ).
Public class RangeAttribute: ValidateAttribute {private int min =-1; private int max =-1; /// <summary> /// constructor /// </summary> /// <param name = "min"> Minimum value </param> /// <param name = "max"> maximum value </param> public RangeAttribute (int min, int max): this (min, max, string. format ("{0} should be between {1} and {2}", "{0}", min, max )) {}/// <summary> /// constructor /// </summary> /// <param name = "min"> Minimum value </param> /// <param name = "ma X "> maximum value </param> /// <param name =" errorMessage "> Verification failure prompt information </param> public RangeAttribute (int min, int max, string errorMessage) {this. min = min; this. max = max; this. errorMessage = errorMessage ;} /// <summary> /// check whether the data is valid /// </summary> /// <param name = "value"> value to be verified </param>/ // <returns> </returns> public override bool Validate (object value) {if (value = null) {return false;} decimal v; if (! Decimal. TryParse (value. ToString (), out v) {return false;} return v >=min & v <= max ;}}View Codepublic class RegexAttribute: ValidateAttribute {private string regex = null; /// <summary> /// constructor /// </summary> /// <param name = "regex"> regular </param> public RegexAttribute (string regex): this (regex, "{0} format error ") {}/// <summary> /// constructor /// </summary> /// <param name = "regex"> regular </param> /// <param name = "errorMessage"> Verification failure prompt </param> public RegexAttribute (string regex, string errorMessage) {this. regex = regex; this. errorMessage = errorMessage ;} /// <summary> /// check whether the data is valid /// </summary> /// <param name = "value"> value to be verified </param>/ // <returns> </returns> public override bool Validate (object value) {if (value = null) {return false;} return new Regex (regex ). isMatch (value. toString ());}}View Codepublic class RegexExpression {/// <summary> // Regular Expression in mobile phone number format (Open number segment: 13 | 4 | 5 | 7 | 8) /// </summary> public const string Mobile = "^ 1 (3 | 4 | 5 | 7 | 8) \ d {9} $ "; /// <summary> /// Regular Expression for Chinese characters (only Chinese characters can be entered without any punctuation marks) /// </summary> public const string Chinese = "^ [\ u4E00-\ u9FFF] + $ "; /// <summary> // mail Regular Expression // </summary> public const string Email = @ "^ ([a-zA-Z0-9 _\. \-]) + \ @ ([a-zA-Z0-9 \-]) + \.) + ([a-zA-Z0-9] {2, 4}) + $ ";}View Code
5. If the result returned by the Validate method is successful or fails, a prompt is returned. Therefore, a validation result class is defined (this part of the code is almost missed ...).
Public class ValidateResult {public ValidateResult () {this. isSuccess = true ;} /// <summary> /// constructor /// </summary> /// <param name = "isSuccess"> whether the verification succeeds </param> /// <param name = "errorMessage"> check failure message </param> public ValidateResult (bool isSuccess, string errorMessage) {this. isSuccess = isSuccess; this. errorMessage = errorMessage;} // <summary> // whether the verification is successful /// </summary> public bool IsSuccess {get; set ;} /// <summary> /// indicates that the check fails. /// </summary> public string ErrorMessage {get; set ;}}View Code
V. Use
1. Define Model
Class User: IValidate {[Caption ("mobile phone number")] [Regex (RegexExpression. mobile)] public string Mobile {get; set;} [Caption ("Age")] [Range (1,120)] public int Age {get; set;} [Range (30,280, "Height Data Exception")] public decimal Height {get; set ;}}View Code
2. Call verification and output results