An example of a filter, model binding in ASP.

Source: Internet
Author: User
This article mainly introduced the detailed ASP. NET MVC Common extension point: Filter, model binding, very practical value, the need for friends can refer to the next

First, filters (filter)

Each request in ASP. NET MVC is assigned to a specific action (hereinafter referred to as "method") under the corresponding controller (hereinafter referred to as "the Controller"), and it is normal to write code directly in the method, but if you want to process some logic before or after the method executes , you need to use a filter here.

There are three commonly used filters: authorize (authorization filter), HandleError (Exception filter), Actionfilter (custom filter), corresponding classes are: Authorizeattribute, Handleerrorattribute and ActionFilterAttribute, inheriting these classes and overriding them to implement different functions.

1.Authorize Authorization Filter

Authorization filters, as the name implies, are licensed, and authorization filters are executed before the method executes to limit the request to enter this method, creating a new method:

Public Jsonresult Authorizefiltertest () {return Json (new Returnmodel_common {msg = "Hello world!"});

Direct access to get results:

Now assume that this authorizefiltertest method is a back-end method, the user must have a valid token to access, the general practice is to receive and verify tokens in the Authorizefiltertest method, but once the method is more, The code that writes the validation in each method is obviously impractical, and this time the authorization filter is used:

public class Tokenvalidateattribute:authorizeattribute {//<summary>///    authorization Authentication logic processing. Returns TRUE if authorized, false instead of//</summary>//    <param name= "HttpContext" ></param>//    < returns></returns>    protected override bool Authorizecore (HttpContextBase HttpContext)    {      String token = httpcontext.request["token"];      if (string. IsNullOrEmpty (token))      {        return false;      }      else      {        return true;}}  }

A new class that inherits Authorizeattribute is created, and the Authorizecore method is overridden, and this pseudo-code implements that token has a value that returns True, and No returns false, annotated to a method that requires authorization to be accessible:

[Tokenvalidate]public jsonresult authorizefiltertest () {  return Json (new Returnmodel_common {msg = "Hello world!"})}

After labeling Tokenvalidate, the Authorizecore method executes before authorizefiltertest, and if Authorizecore returns True, Then the authorization succeeds executes the code inside the Authorizefiltertest, otherwise the authorization fails. Do not send tokens:

Token transfer:

No token authorization fails when you enter the default unauthorized page of MVC. Here is the improvement: whether the authorization is successful or failure to ensure that the return value format consistent, convenient front-end processing, this time to rewrite the Authorizeattribute class Handleunauthorizedrequest method:

<summary>///authorization failure handling//</summary>///<param name= "Filtercontext" ></param>protected override void Handleunauthorizedrequest (AuthorizationContext filtercontext) {  base. Handleunauthorizedrequest (filtercontext);  var json = new Jsonresult ();  Json. Data = new Returnmodel_common  {    success = false,    code = Returncode_interface.token Expired or error,    msg = "token Expired or error "  };  Json. Jsonrequestbehavior = Jsonrequestbehavior.allowget;  Filtercontext.result = JSON;}

Effect:

Actual Combat: Authorization Filter The most extensive application or do a rights management system, the user login successful after the server output an encrypted token, subsequent requests will take this token, the service side in the Authorizecore method to unlock token to get the user ID, According to the user ID to go to the database to check if there is permission to request the current interface, there is a return true, the reverse returns false. This way of authorizing, compared to the success of the login to the cookie and the session benefit is an interface between the PC side, the app side common use.

2.HandleError exception Filter

Exception filters are handling code exceptions, which are executed when the system's code is misplaced, MVC has implemented an exception filter by default and is registered to the FilterConfig.cs in the App_start directory:

Filters. ADD (New Handleerrorattribute ());

This takes effect in the entire system, any interface or page error will perform MVC default exception handling, and return a default error page: Views/shared/error (the program sent to the server to report a mistake to see this page, local debugging permissions high, or you can see the specific error message)

@{  Layout = null;} <! DOCTYPE html>

The default exception filter is obviously not enough to meet the needs of the use, rewrite the exception filter, to cope with the actual project requirements:

1) Errors can record the error code where the controller and method, as well as the request parameters and time;

2) returns JSON in a specific format for easy front-end processing. Because most of the system is the AJAX request, error returned to the MVC default error page, the front end is not good to handle

Create a new class Logexceptionattribute inherit Handleerrorattribute, and override the internal Onexception method:

 public override void Onexception (Exceptioncontext filtercontext) {if (!filtercontext.exceptionhandled) {string     Controllername = (string) filtercontext.routedata.values["Controller";     String actionname = (string) filtercontext.routedata.values["action";     string param = Common.getpostparas ();     string ip = HttpContext.Current.Request.UserHostAddress; Logmanager.getlogger ("Logexceptionattribute"). Error ("Location:{0}/{1} Param:{2}userip:{3} exception:{4}", Controllername, ActionName, Param, IP,     FilterContext.Exception.Message); Filtercontext.result = new Jsonresult {Data = new Returnmodel_common {success = false, Code = Returncode_inter   Face. Server error, MSG = FilterContext.Exception.Message}, Jsonrequestbehavior = Jsonrequestbehavior.allowget};     if (Filtercontext.result is jsonresult) filtercontext.exceptionhandled = true;//return result is Jsonresult, set exception handled by else Base. Onexception (Filtercontext);//Perform base class Handleerrorattribute logic, turn to error page}

Exception filters are not labeled as authorization filters on the method, directly to the App_start directory under the FilterConfig.cs registration, so that all the interfaces can be effective:

Filters. ADD (New Logexceptionattribute ());

The exception filter uses Nlog as the logging tool, the NuGet installation command:

Install-package Nloginstall-package Nlog.config

Compared to Log4net,nlog configuration is simple, only a few lines of code, Nlog.config:

<?xml version= "1.0" encoding= "Utf-8"? ><nlog xmlns= "Http://www.nlog-project.org/schemas/NLog.xsd" xmlns: xsi= "Http://www.w3.org/2001/XMLSchema-instance" > <targets>  <target xsi:type= "File" name= "F" Filename= "${basedir}/log/${shortdate}.log" layout= "${uppercase:${level}} ${longdate} ${message}"/>  < Target xsi:type= "File" name= "F2" filename= "D:\log\mvcextension\${shortdate}.log" layout= "${uppercase:${level}} ${ Longdate} ${message} "/> </targets> <rules>  <logger name=" * "minlevel=" Debug "writeto=" F2 "/> </rules></nlog>

If the error, the log is recorded in the D drive log directory under the Mvcextension directory, a project a log directory, easy to manage. Complete the configuration and look at the code:

Public Jsonresult handleerrorfiltertest () {  int i = Int. Parse ("abc");  Return Json (new Returnmodel_data {Data = i});}

string strong to int type, must error, page response:

The logs are also recorded:

3.ActionFilter Custom Filters

Custom filters are more flexible and can be injected precisely before, during, and after a request. Inherit the abstract class ActionFilterAttribute and rewrite the method inside:

public class systemlogattribute:actionfilterattribute{public string Operate {get; set;}    public override void OnActionExecuted (ActionExecutedContext filtercontext) {    FilterContext.HttpContext.Response.Write ("<br/>" + Operate + ": onactionexecuted"); Base.  OnActionExecuted (Filtercontext); } public override void OnActionExecuting (ActionExecutingContext filtercontext) {FILTERCONTEXT.HTTPCONTEXT.RESPONSE.W    Rite ("<br/>" + Operate + ": onactionexecuting"); Base.  OnActionExecuting (Filtercontext); } public override void Onresultexecuted (ResultExecutedContext filtercontext) {FilterContext.HttpContext.Response.Wri    Te ("<br/>" + Operate + ": onresultexecuted"); Base.  Onresultexecuted (Filtercontext); } public override void Onresultexecuting (ResultExecutingContext filtercontext) {FILTERCONTEXT.HTTPCONTEXT.RESPONSE.W    Rite ("<br/>" + Operate + ": onresultexecuting"); Base.  Onresultexecuting (Filtercontext); }}

This filter is suitable for the system operation log logging function:

[Systemlog (Operate = "Add User")]public string Customerfiltertest () {  Response.Write ("<br/>action in Execution ...");  Return "<br/>action execution End";}

Look at the results:

Four method execution order: onactionexecuting->onactionexecuted->onresultexecuting->onresultexecuted, which controls the entire request process very precisely.

In the actual combat record log process is this: in the OnActionExecuting method to write an operation log into the database, the global variable to save the record of the primary key, to the Onresultexecuted method to explain the request is over, this time naturally know the user's operation is successful , the Success field for this operation log is updated according to the primary key.

Second, model binding (Modelbinder)

Let's look at an ordinary method:

Public ActionResult Index (Student Student) {  return View ();}

This method accepts the argument is a student object, the front-end passed arguments with the student object in the property remains, then automatically bound to this object, do not need to new student in the method object and bound property, The process of binding is done by Defaultmodelbinder in MVC, and Defaultmodelbinder inherits the Imodelbinder interface at the same time. The Imodelbinder interface and the Defaultmodelbinder are now used to achieve more flexible model binding.

Scene one, the front end passed an encrypted string token, the method needs to use some of the token in the field, it must be in the method to receive the string, decrypt the string, converted to object, so a method is good to say, many words repeat code very much, even if the extraction of common methods, Or to call this generic method in the method, is there any way to encapsulate the object directly in the parameter?

Model-bound objects:

public class tokenmodel{//<summary>/////  </summary> public  int Id {get; set;}  <summary>///Name:///  </summary> Public  string name {set; get;}  <summary>//About//  </summary> public  string Description {get; set;}}

Create a new Tokenbinder to inherit the Imodelbinder interface and implement the Bindmodel method in it:

public class tokenbinder:imodelbinder{Public  object Bindmodel (ControllerContext controllercontext, Modelbindingcontext BindingContext)  {    var token = controllercontext.httpcontext.request["token"];    if (!string. IsNullOrEmpty (token))    {      string[] array = token. Split (': ');      if (array. Length = = 3)      {        return new Tokenmodel () {Id = Int. Parse (Array[0]), Name = array[1], Description = array[2]};      }      else      {        return new Tokenmodel () {Id = 0};      }    }    else    {      return new Tokenmodel () {Id = 0};    }  }}

This method takes a token parameter and parses and encapsulates the token parameter. The code section completes the need to register in the Application_Start method:

ModelBinders.Binders.Add (typeof (Tokenmodel), New Tokenbinder ());

Now simulate this interface:

Public Jsonresult tokenbindertest (Tokenmodel tokenmodel) {  var output = "Id:" + tokenmodel.id + ", Name:" + TOKENMODEL.N Ame + ", Description:" + tokenmodel.description;  Return Json (new Returnmodel_common {msg = output});}

Called under:

As can be seen, "1: Wangyai: oppoic.cnblogs.com" has been bound to tokenmodel this object. But if a slightly more complex model binds imodelbinder, there is nothing to do.

Scene Two, remove the first space of a property of an object

public class student{Public  int Id {get; set;}  public string Name {get; set;}  public string Class {get; set;}}

If there are spaces in the Name property of the front end, how do you get rid of it? Enables more flexible control with Defaultmodelbinder

public class trimmodelbinder:defaultmodelbinder{  protected Override Object GetPropertyValue (ControllerContext ControllerContext, Modelbindingcontext BindingContext, PropertyDescriptor PropertyDescriptor, IModelBinder Propertybinder)  {    var obj = base. GetPropertyValue (ControllerContext, BindingContext, PropertyDescriptor, propertybinder);    if (obj is string && propertydescriptor.attributes[typeof (trimattribute)]! = NULL)//is judged to be of type string and has a [Trim] tag    {      return (obj as String). Trim ();    }    return obj;  }}

Label the entities that need to format the first attribute:

[Modelbinder (typeof (Trimmodelbinder))]public class student{public  int Id {get; set;}  [Trim]  public string Name {get; set;}  public string Class {get; set;}}

Well, under test:

Public Jsonresult trimbindertest (Student Student) {  if (string. IsNullOrEmpty (student. Name) | | String. IsNullOrEmpty (student. Class)  {    return Json (new Returnmodel_common {msg = "parameter not Found"});  else  {    return Json (new Returnmodel_common {msg = "Name:" + student. Name + ", Length:" + student. Name.length + "Class:" + student. Class + ", Length:" + student. Class.length});}  }

Visible, the name length of the Trim property is the length of the stripped space: 7, and the length of the class attribute without the callout is 6.

"Recommended"

1. ASP. NET free Video Tutorials

2. ASP. NET Tutorials

3. Geek College asp,net Video Tutorial

Related Article

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.