Now that you have a Web project with an MVC architecture, you have to complete a registration feature.
The front desk has passed 3 values to your controller, namely the account number, the password, the mailbox.
Now you have to judge in the controller, the account name, password, mailbox can not be empty, and the name and password does not exceed 16 bits.
The above diagram is just a small example of the ideal, and the actual development is that you might want to pass more than 10 or more fields at a time.
So in actual development , usually for reusability , we replace these 3 parameters with an entity class .
as shown below.
Note: This step will have a knowledge point, called model verification, do not understand the children's shoes can be Baidu, MVC will be a certain rule automatically directly deserialize the parameters into the corresponding entity class, but because I this example is WEBAPI mode, the wording slightly different, so also to add a [frombody] in front of the parameter To be automatically deserialized.
As to the specific why will automatically deserialize, in this article is not my topic, so interested in children's shoes can be Baidu under: MVC under the Modelbinder.
Decoupling of the interception layer
Now, I think it's a little bit less beautiful to put the entity class validation to the controller, and if there are many business rules, then this kind of validation code is huge, and if the entire project is using this validation model, then I feel a bit bloated in my later maintenance phase. Entity classes rely on the Controller method to verify, I have to find this entity class, and then carefully think of what methods to use the entity class, and what validation judgment, and then maintenance.
So can I verify the entity class in the Controller method This step is removed, not written to the Controller method, written in another place, unified management, to achieve the validation of the entity class and the method of the Controller business logic division.
This behavior is a bit like HttpModule, the thought is the design pattern so-called reduced coupling.
So how do you do it?
We can add validation directly to the entity class,
The above see [required],[stringlength],[regularexpression] is called the validation feature, which is already encapsulated by the. NET Framework, which validates the fields of the callout attribute.
[Required] Limited required input, [Required (errormessage = "Please enter user name")]
[Stringlength] limits the specified length, [Stringlength (x, errormessage = "Length cannot exceed 10 characters")]
[Range] limits the range of values, [range (0, errormessage = "age range between 0-120 years old")]
[RegularExpression] limits the need to satisfy regular expressions, [RegularExpression (@"^\w+ ([-+.] \w+) *@\w+ ([-.] \w+) *\.\w+ ([-.] \w+) *$ ", errormessage = " Please enter email format ")]
[Compare] restricts the corresponding fields to be equal, [Compare ("pwd", errormessage = "two times password to be consistent")]//The attribute label must be equal to the PWD field value
. NET also encapsulates a few, these 5 use the most (of course, can also customize this authentication feature, for this piece want to know deeply about Baidu: MVC Validationattribute).
So how do I judge a feature after I mark it?
Let's look at the notation in the controller method:
, using Modelstate.isvalid to determine the validation result, true if the marked attribute on the entity class satisfies the condition, or False.
So, because this model validation is a pattern and is global, it should be taken out separately to register at the interception layer.
This code means: each time you enter the controller method, you will determine the name of the method, if it contains any of the INSERT, check, UPDATE, any one of the three, will be intercepted verification (the results of the model validation), if False, Then return a 400 status code to the client.
Then sign up: (The place to register is just an example, because I'm a webapi, I intercept HTTP only)
Model is responsible for filling in the rules, verification by the special verification personnel to do, logic by the special logic staff to write, so that their respective roles.
However, this is only the first step!
(as you develop on a daily basis, you will certainly encounter this situation)
User entity class, is focused on the registration method, plainly, is written for the registration method,
I'm going to write a login method now.
But when logged in, I do not need to fill in the email, only need to fill in the account number and password, the two fields to verify.
But my entity class inside the email did [Required] and [regularexpression] authentication, then this will cause if I login method continue to use the user entity class, then will definitely error, will return a 400 verification code.
How can i solve this situation? Should we build a model again? and give the rules back again? This is just 3 fields, what if there are more than 10 fields in the table, more than 20 fields or more?
Re-build a model certainly not, so has lost the reusability, the original intention of their respective roles.
Solutions! Online and so on!
...
Model Validation Advanced: Free control of fields to validate
Baidu has a bit, online no such aspects of the tutorial, blog Park also did not find, the group did not communicate a result, but this situation is often encountered!
Comb the idea, there are roughly several, the first is to use some means to control the class of these validation features, or control the class of attribute fields, such as enable or disable, but C # cannot disable the attribute fields, and the control class of these validation features is a bit of a fantasy, in itself is the Microsoft package is good, You have to decompile and look at the source code, and then refactor? Or do you directly use these frameworks to encapsulate the validation features, define custom validation features yourself, and then write the control methods in it? It's too much trouble, and it's against the original. Custom Modelbinder? more nonsense.
Some toss no fruit, then can not from the characteristics itself to find a breakthrough, at this time, I transferred the target to Modelstate.isvalid, a change of ideas to achieve.
We find that it implements the GetEnumerator method, and then iterates over it to get the name of the field property to which the attribute is bound and its state.
Because you want to implement free control of the fields that need to be validated, no matter how it is implemented, it can only be implemented by custom attribute labeling on the method body header.
and the ideal final result should be this:
To put a picture:
Or
How to use:
If there is a KEEPZ feature on the method head, enter the free control validation field state.
[Keepz ("Field 1", "Field 2")] that is: Validation only for field 1 and Field 2
[Keepz (False, "Field 3")] that is: Except for Field 3, the remaining fields are validated
So let's put down the implementation code:
Public Override voidonactionexecuting (Httpactioncontext actioncontext) {if(ActionContext.ActionDescriptor.ActionName.ToUpper (). Contains ("INSERT") || ActionContext.ActionDescriptor.ActionName.ToUpper (). Contains ("CHECK") ||ActionContext.ActionDescriptor.ActionName.ToUpper (). Contains ("UPDATE"))) { varIA = actioncontext.actiondescriptor.getcustomattributes<keepz>(); if(IA. Count! =1) { Gotoresult; } foreach(keyvaluepair<string, modelstate> IteminchActionContext.ModelState.ToArray ()) { if(ia[0]. Modes = =false) { foreach(stringPropertysvalueinchia[0]. Propertys) {if(item. Key.contains (Propertysvalue)) {ActionContext.ModelState.Remove ( Item. Key); } } } Else { BOOLRe =false; foreach(stringPropertysvalueinchia[0]. Propertys) {if(item. Key.contains (Propertysvalue)) {Re=true; } } if(Re = =false{actionContext.ModelState.Remove (item). Key); }}} Result:if(!actionContext.ModelState.IsValid) { for(inti =0; i < ActionContext.ModelState.Count; i++) { if(ActionContext.ModelState.Values.ToList () [i]. Errors.Count >0&& actionContext.ModelState.Values.ToList () [i]. Value! =NULL) {Actioncontext.response=actionContext.Request.CreateErrorResponse (Httpstatuscode.badrequest, actioncontext.modelstate); Break; } } } } }
/// <summary> ///Keep/// </summary> Public classKeepz:attribute { Public string[] Propertys =NULL; Public BOOLModes =true; PublicKEEPZ (params string[] property) {Propertys=Property ; } PublicKEEPZ (BOOLMode,params string[] property) {Propertys=Property ; Modes=Mode; } }
In this way, it is necessary to rebuild the model such a low-end method, and now most of the MVC architecture with this authentication mode, but there is no free choice to verify the field of the solution, often encountered this situation, can only be helpless to re-build an entity class, in contrast, there is no food to the essence of the interception layer model verification, Only learn a mold, instead of self-defeating is not the intention, so I wrote this and everyone to share, joined the KEEPZ to control the need to verify the field, is the real implementation of the reusable, logic and interception layered.
Demo is small, but the solution in this case, I did not find in the blog park, it should be the first in the garden.
Xiao Zeng
Source: http://www.cnblogs.com/1996V/p/7423834.html Welcome reprint, but any reprint must retain the complete article, in the prominent place displays the signature as well as the original text link. If you have any questions or authorization to negotiate, please leave me a message
. NET advanced step, WEBAPI and MVC when model validation, teach you how to freely control the fields that need to be validated?