MVC data validation principle and custom Modelvalidatorprovider implementation without compilation modify validation rules and error messages

Source: Internet
Author: User

Provides a very simple and easy-to-use data validation solution in ASP. By System.ComponentModel.DataAnnotations providing a lot of validation rules (Required, stringlength, etc.). However, there are often such requirements, we want to be able to save the model validation rules to the data or XML files, rather than the code, the advantage is that we can easily modify the validation rules and error messages, to avoid the need to republish the site.

In this article, let's look at how you can configure validation of the model with the XML file through a custom modelvalidatorprovider.

Read the catalogue:

A simple review of the use of built-in MVC validation

Ii. analyzing the internal process of MVC validation

A city example, validation for ContactInfo

Iv. Concrete realization and application of Xmlmodelvalidatorprovider

One, a simple review of the use of built-in MVC validation

The following are typical MVC validation rules for Code and page presentation effects.

 

Second, analyzing the internal process of MVC validation

1. The actual verification is modelvalidator

When we like, after adding a variety of validation rules for the person class dataannotation attributes, the actual fencing to do validation is DataAnnotationsModelValidator类.
DataAnnotationsModelValidator inherited from the abstract class modelvalidator, the implementation of the abstract method validate, In this method, the instance of all person is validated against the validation rules defined in the person class, and a collection of Modelvalidationresult is returned.

2. Modelvalidator is provided by modelvalidatorproviders

The modelvalidator used by MVC in the validation process is also provided by the Modelvalidatorproviders class, and Modelvalidatorproviders is an abstract class with an abstract method getvalidators.

The definition of the class is like this

namespace system.web.mvc{public    abstract class Modelvalidatorprovider    {public        abstract ienumerable< Modelvalidator> getvalidators (Modelmetadata metadata, ControllerContext context);}    }

In practice, MVC uses a Dataannotationsmodelvalidatorprovider class that inherits from Modelvalidatorprovider and implements the Getvalidators method.

3. The MVC validation process can exist in multipleModelValidatorProvider

MVC can have multiple modelvalidatorprovider at the same time, their effects can be superimposed. We can use the default Dataannotationsmodelvalidatorprovider to define validation rules based on attribute, You can also use our xmlmodelvalidatorprovider below to get validation rules from an XML file for validation.

Three, an example, for the validation of ContactInfo

The following ContactInfo class is what we use to do the actual verification, including some common typical authentication, Required, Email, URL, etc.

public class contactinfo{Public    string FirstName {get; set;}    public string Lastname{get;set;}    public string Email{get;set;}    

The following XML file, which defines the validation rules for the ContactInfo class, was previously written in the ContactInfo class, and now separates it and puts it into content\validation\rules\ The Contactinfo.xml file.

The value in the message here is just a key to the message, and the specific content of the message is placed in another XML file.

<?xml version= "1.0" encoding= "Utf-8"?><model> <validator property= "FirstName" type= "Required" message = "firstname_required"/> <validator property= "FirstName" type= "Stringlength" arg-int= "message=" FirstName_ Length "/> <validator property=" LastName "type=" Required "message=" lastname_required "/> <validator Proper Ty= "LastName" type= "stringlength" arg-int= "255" message= "Lastname_length"/> <validator property= "Email" type= " Required "message=" email_required "/> <validator property=" Email "type=" stringlength "arg-int=" 255 "message=" Email_length "/> <validator property=" Email "type=" RegularExpression "arg=" ^[\w-]+ (\.[ \w-]+) *@[\w-]+ (\.[ \w-]+) +$ "message=" email_regularexpression "/> <validator property=" Url "type=" stringlength "arg-int=" 255 " Message= "Url_length"/> <validator property= "Url" type= "RegularExpression" arg= "(/http)? (www\.)? \w+\.  (com|net|edu|org) "message=" Url_regularexpression "/></model>

The message is stored in the Content\validation\messages\contactinfo.xml file

<?xml version= "1.0" encoding= "Utf-8"?><messages>  <!--filed error message--  <message key= "firstname_required" text= "The Frist Name field is Required." ></message>  <message key= "Firstname_length" text= "the field maximum Length is" ></message>  <message key= "lastname_required" text= "The last Name field is Required." ></message>  <message key= "Lastname_length" text= "the field maximum Length is 255" ></message>  <message key= "email_required" text= "The Email field is Required." ></message>  <message key= "Email_length" text= "the field maximum Length is 255" ></message>  <message key= "email_regularexpression" text= "Invalid Email." ></message>  <message key= "Url_length" text= "the field maximum Length is 255" ></message>  
Iv. implementation and application of Xmlmodelvalidatorprovider

Here is the implementation code of our most important xmlmodelvalidatorprovider

public class xmlmodelvalidatorprovider:modelvalidatorprovider{//is used to save the existing test in System.ComponentModel.DataAnnotations       Rules, that is, MVC's own required and other validation rules, because we just verify that the rule "source" is not the same, one is the code, one is XML, but the validation process is the same, so to reuse the already written validation in MVC.       Private ReadOnly dictionary<string, type> _validatortypes;       Private readonly String _xmlfolderpath = HttpContext.Current.Server.MapPath ("~//content//validation//rules"); Public Xmlmodelvalidatorprovider () {
_validatortypes = Assembly.Load ("System.ComponentModel.DataAnnotations"). GetTypes (). Where (t = t.issubclassof (typeof (Validationattribute))). ToDictionary (t = t.name, t = t); } #region Stolen from Dataannotationsmodelvalidatorprovider//delegate, converts Validationattribute into Dataannotationsmodelvalidator internal static Dataannotationsmodelvalidationfactory defaultattributefactory = (metadata, context, attribute) = new Dataannotationsmodelvalidator (metadata, context, attribute); Internal static Dictionary<type, dataannotationsmodelvalidationfactory> attributefactories = new Dictionary <type, dataannotationsmodelvalidationfactory> { { typeof (Rangeattribute), (Metadata, Contex T, attribute) = NE W Rangeattributeadapter (metadata, context, (Rangeattribute) attribute) }, { typeof (Regularexpressionattribute), (metadata, context, attribute) = New Regularexpressionattributeadapter (metadata, context, Regula Rexpressionattribute) attribute) }, {ty Peof (RequiredAttribute), (metadata, context, attribute) = New Requiredattributeadapter (metadata, context, (RequiredAttribute) attribute) }, { typeof (Stringlengthattribute), (metadata, context, attribute) = New String Lengthattributeadapter (metadata, context, (Stringlengthattribute) attribute) } }; #endregion//Overrides the Getvalidators method, which is obtained from the XML file. Based on the configuration of the XML, return the corresponding validator collection public override ienumerable<modelvalidator> getvalidators (Modelmetadata metadata, Co Ntrollercontext context) {var results = new list<modelvalidator> (); Whether the validation is for a property or model//(remember we can apply validation attributes to a proper Ty or model and same applies here as well) var ispropertyvalidation = metadata. Containertype! = NULL &&! String.IsNullOrEmpty (metadata. PropertyName); var Rulespath = String.Format ("{0}\\{1}.xml", _xmlfolderpath, Ispropertyvalidation ? Metadata. ContainerType.Name:metadata. Modeltype.name); var rules = file.exists (Rulespath)? Xelement.load (Rulespath). Xpathselectelements (String.Format ("./validator[@property = ' {0} ']", Ispropertyvalidation? Metadata. Propertyname:metadata. Modeltype.name)). ToList (): New list<xelement> (); produce a validator for each validation attribute we find foreach (var rule in rules) { Dataannotationsmodelvalidationfactory Factory; var validatortype = _validatortypes[string.concat (rule. Attribute ("type"). Value, "Attribute")]; if (! Attributefactories.trygetvalue (Validatortype, Out factory)) {factory = Defaultattributefa Ctory; } var validator = (Validationattribute) activator.createinstance (Validatortype, getvalidationargs (rule)); Validator. errormessage = rule. Attribute ("message")! = NULL &&! String.IsNullOrEmpty (rule. Attribute ("message"). Value)? Getvalidationmessage (ispropertyvalidation metadata. CoNtainerType.Name:metadata. Modeltype.name, rule. Attribute ("message"). Value): null; Results. ADD (Factory (metadata, context, validator)); } return results; } private String Getvalidationmessage (string model, string key) {return Messageprovider.getviewmode Lvalidationmessage (model, key); }//Read the arguments passed to the validation attribute and cast it their respective type. Private object[] Getvalidationargs (XElement rule) {var Validatorargs = rule. Attributes (). Where (A = a.name.tostring (). StartsWith ("Arg")); var args = new Object[validatorargs.count ()]; var i = 0; foreach (var arg in Validatorargs) {var argname = arg. Name.tostring (); var argvalue = arg. Value; if (!argname.contains ("-")) {args[i] = Argvalue; } else {var argtype = argname.split ('-') [1]; Switch (argtype) {case "int": args[i] = Int. Parse (Argvalue); Break Case "datetime": args[i] = DateTime.Parse (argvalue); Break Case "char": args[i] = Char.parse (argvalue); Break Case "Double": args[i] = Double.Parse (argvalue); Break Case "decimal": args[i] = Decimal.Parse (argvalue); Break Case "bool": args[i] = Boolean.Parse (argvalue); Break Default:args[i] = Argvalue; Break }}} return args; } }

Finally, in the Global.cs file, add Xmlmodelvalidatorprovider to the MVC modelvalidatorproviderscollection

MODELVALIDATORPROVIDERS.PROVIDERS.ADD (New Xmlmodelvalidatorprovider ());

MVC data validation principle and custom Modelvalidatorprovider implementation without compilation modify validation rules and error messages

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.