ASP. Mvc-filter

Source: Internet
Author: User
Tags httpcontext actionlink

Filter is a design based on AOP (aspect-oriented programming) that injects additional logic into the MVC framework's processing of client requests and implements crosscutting concerns in a very simple and graceful way (cross-cutting concerns). Crosscutting concerns refer to the functionality of multiple or even all modules that traverse the program, and classic crosscutting concerns include logging, caching processing, exception handling, and authorization validation. This article describes the creation and use of different kinds of filter supported by the MVC framework, and how to control their execution. Overview of the four basic Filter

The filter supported by the MVC framework can be categorized into four classes, each of which can introduce additional logic processing at different points in time for processing requests. These four categories filter the following table:

Before the MVC framework calls Acion, it will first determine if there is an attribute that implements the interface in the table above, and if so, the method defined in the attribute is called at the appropriate point in the request pipeline.

The MVC framework implements the default attribute classes for these kinds of filter interfaces. As shown in the table above, the ActionFilterAttribute class implements the Iactionfilter and Iresultfilter two interfaces, which is an abstract class that must be provided for implementation. The other two feature classes, Authorizeattribute and Handleerrorattribute, have provided some useful methods that can be used directly.

The filter can be applied to a single ation method as well as the entire controller, and multiple filter can be applied on the acion and controller. As shown below:

[Authorize (roles= "Trader")]  Valid for all action public class Examplecontroller:controller {      [showmessage]  ///For current ation    [OutputCache ( DURATION=60)]//ation active public    actionresult Index () {         //...      }}

Note that for the base class of a custom controller, the filter applied to the base class will also be valid for all subclasses that inherit from the base class.

Authorization Filter

Authorization filter is run before the action method and other kinds of filter. Its role is to enforce a permission policy that guarantees that the action method can only be called by authorized users. The interface implemented by the Authorization filter is as follows:

namespace SYSTEM.WEB.MVC {Public    interface Iauthorizationfilter {         void onauthorization (AuthorizationContext Filtercontext);     
Custom Authorization Filter

You can implement the Iauthorizationfilter interface yourself to create your own security authentication logic, but this is generally not necessary or recommended. If you want to customize the security authentication policy, the more secure way is to inherit the default Authorizeattribute class.

Below we demonstrate the custom authorization Filter by inheriting the Authorizeattribute class. Create a new empty MVC application, add a Infrastructure folder as usual, and add a CustomAuthAttribute.cs class file with the following code:

namespace Mvcapplication1.infrastructure {public    class Customauthattribute:authorizeattribute {        private BOOL localallowed;        Public Customauthattribute (bool allowedparam) {            localallowed = Allowedparam;        }        protected override bool Authorizecore (HttpContextBase HttpContext) {            if (httpContext.Request.IsLocal) {                return localallowed;            }            else {                return true;}}}    }

This simple filter, by overriding the Authorizecore method, allows us to block a local request, and when the filter is applied, the constructor can be used to specify whether to allow local requests. Authorizeattribte class helps us to implement a lot of things, we just focus on the Authorizecore method, in this method to implement the logic of authorization authentication.

To demonstrate the effect of this filter, we create a new controller named Home, and then apply the filter on the Index action method. The parameter is set to False to protect this action from being accessed locally, as follows:

public class Homecontroller:controller {    [CustomAuth (false)] public    string Index () {        return ' this is the Ind Ex action on the Home controller ";    }}

Run the program, based on the default route values generated by the system,/home/index the request, with the following results:

We customize a simple filter by using the Authorizeattribute class as the base class, so what are the useful functions of the Authorizeattribute class itself as a filter?

Using the built-in authorization Filter

When we use the Authorizeattribute class as a filter directly, we can specify our permission policy with two properties. The two properties and descriptions are as follows:

    • The Users property, string type, specifies the user name that allows access to the action method, and multiple user names are separated by commas.
    • Roles property, String type, comma-delimited role name, the user accessing the action method must belong to one of these roles.

Use the following:

public class Homecontroller:controller {    [Authorize (Users = "Jim, Steve, Jack", Roles = "admin")] public    string Index () {        return "This is the Index action on the Home controller";    }}

Here we apply the authorize attribute to the index method and specify the users and roles that can access the method. To access the index action, both must satisfy the condition that the user name must be one of Jim, Steve, Jack, and must have the attribute Admin role.

In addition, if you do not specify any user name and role name (that is, [authorize]), the action method can be accessed by the logged-on user only.

You can look at the effect by creating an Internet template application, which is not shown here.

For most applications, the permissions policy provided by the Authorizeattribute attribute class is sufficient. If you have special needs, you can do so by inheriting the Authorizeattribute class.

Exception Filter

Exception Filter, which runs when an unhandled exception is thrown in the following three sources:

    • Another filter (such as filter authorization, action, or result).
    • The action method itself.
    • The action method executes (that is, when the ActionResult is processed).

The Exception filter must implement the Iexceptionfilter interface, which is defined as follows:

namespace SYSTEM.WEB.MVC {Public     interface Iexceptionfilter {         void onexception (Exceptioncontext Filtercontext);     
Exceptioncontext Common Property Descriptions

In the Iexceptionfilter interface definition, the only Onexception method executes when an unhandled exception is thrown, where the type of the parameter: Exceptioncontext, which inherits from the ControllerContext class, ControllerContext contains the following common properties:

    • Controller that returns the controller object for the current request.
    • HttpContext, providing detailed information about the request and response.
    • Ischildaction returns True if it is a child action (a child action is briefly described later).
    • RequestContext, which provides request context information.
    • Routedata, the routing instance information for the current request.

As a subclass of the inheriting ControllerContext class, the Exceptioncontext class also provides the following common properties for handling exceptions:

    • Actiondescriptor, provides detailed information about the action method.
    • Result, which is a actionresult type, allows the execution of a filter to be canceled by setting this property value to non-null.
    • Exception, exception information is not handled.
    • Exceptionhandled returns True if another filter marks the exception as handled.

A exception filter can be labeled by setting the Exceptionhandled property to true to mark that the exception has been processed, which is typically used when multiple exception filter is applied on an action method. After the Exceptionhandled property is set to True, the value of the property can be used to determine whether the other application is in the same action method exception the filter has handled the exception, lest the same exception be processed repeatedly in different filter.

Sample Demo

Under the Infrastructure folder, add a RangeExceptionAttribute.cs class file with the following code:

public class Rangeexceptionattribute:filterattribute, iexceptionfilter {public    void onexception ( Exceptioncontext filtercontext) {        if (!filtercontext.exceptionhandled && filtercontext.exception is ArgumentOutOfRangeException) {            Filtercontext.result = new Redirectresult ("~/content/rangeerrorpage.html");            filtercontext.exceptionhandled = True;}}    }

This exception filter displays friendly ArgumentOutOfRangeException exception information by redirecting to a static HTML file in the content directory. The Rangeexceptionattribute class we define inherits the FilterAttribute class and implements the Iexception interface. As an MVC Filter, its class must implement the Imvcfilter interface, you can implement this interface directly, but the simpler way is to inherit the FilterAttribute base class, which implements some necessary interfaces and provides some useful basic features. For example, the filter is processed in the default order.

Add a file named rangeerrorpage.html below the content folder to display friendly error messages. As shown below:

<! DOCTYPE html> 

Adding a value in HomeController throws the exception's action as follows:

    public class Homecontroller:controller {         [rangeexception] public        string rangetest (int id) {             if (ID > 100) {                 return String.Format ("The ID value is: {0}", id);             } else {                 throw new ArgumentOutOfRangeException ("id", ID, "");             }         }     

When you apply a custom exception filter to Rangetest, the Run Program URL request is/home/rangetest/50 and the program throws an exception and redirects to the rangeerrorpage.html page:

Because the static HTML file is detached from the background, the actual project is more of a view to render a friendly error message, so that it can be a good dynamic control. As the example changes below, the Rangeexceptionattribute class is modified as follows:

    public class Rangeexceptionattribute:filterattribute, iexceptionfilter {public        void onexception ( Exceptioncontext filtercontext) {            if (!filtercontext.exceptionhandled && filtercontext.exception is ArgumentOutOfRangeException) {                int val = (int) (((ArgumentOutOfRangeException) filtercontext.exception). Actualvalue);                Filtercontext.result = new ViewResult {                    ViewName = "Rangeerror",                    ViewData = new viewdatadictionary<int>
    (val) };                filtercontext.exceptionhandled = True;}}    }

We create a Viewresult object that specifies the view name and the passed model object to redirect when an exception occurs. Then we add a rangeerror.cshtml file under the Views/shared folder with the following code:

@model int<! DOCTYPE html> 

The results of the operation are as follows:

Disable exception Tracking

Many times exceptions are unpredictable, and applying exception filter on each action method or controller is unrealistic. And the filter cannot be applied if the exception appears in view. As rangeerror.cshtml this view add the following code:

@model int@{     var count = 0;     var number = Model/count; } ...

After you run the program, the following information is displayed:

Obviously this information should not be displayed to the user after the program is published. We can configure Web. config to show uniform, friendly error messages regardless of when and where the application throws an exception. Add the following sub-nodes under the <system.web> node in the Web. config file:

  <system.web> ...    <customerrors mode= "on" defaultredirect= "/content/rangeerrorpage.html"/>  </system.web>

This configuration is only valid for remote access, and the local run site still displays trace information.

Using the built-in Exceptin Filter

With the demonstration above, we understand how Exceptin filter works behind MVC. But we don't often create our own Exceptin Filter, because Microsoft's built-in Handleerrorattribute in the MVC framework (which implements the Iexceptionfilter interface) is enough for our usual use. It contains Exceptiontype, view, and master three properties. When an exception of the specified type of the Exceptiontype property is raised, the filter renders a page with the view specified by the View property, using the layout specified by the default layout or Mast property. As shown in the following code:

... [HandleError (Exceptiontype = typeof (ArgumentOutOfRangeException), View = "Rangeerror")] public string rangetest (int id) {     if (id >) {         return String.Format ("The ID value is: {0}", id);     } else {         throw new Argumentoutofran Geexception ("id", ID, "");     

Using the built-in Handleerrorattribute, when the exception information is presented to the view, this feature also passes a Handleerrorinfo object as the model of the view. The Handleerrorinfo class contains the ActionName, Controllername, and Exception properties, as the following rangeerror.cshtml uses this model to render information:

@model handleerrorinfo @{     viewbag.title = "Sorry, there was a problem!";}  <! DOCTYPE html> 
Action Filter

As the name implies, action filter "Filters" The execution of the action method, including before and after execution. It needs to implement the Iactionfilter interface, which is defined as follows:

namespace SYSTEM.WEB.MVC {Public     interface Iactionfilter {         void onactionexecuting (ActionExecutingContext Filtercontext);         void onactionexecuted (ActionExecutedContext filtercontext);     } }

Where the OnActionExecuting method is called before the action method executes, the OnActionExecuted method is called after the action method executes. Let's look at a simple example.
Under the Infrastructure folder, add a Profileactionattribute class with the following code:

Using System.Diagnostics; Using SYSTEM.WEB.MVC; namespace Mvcapplication1.infrastructure {Public     class Profileactionattribute:filterattribute, Iactionfilter { C1/>private Stopwatch timer;         public void onactionexecuting (ActionExecutingContext filtercontext) {             timer = stopwatch.startnew ();         }         public void onactionexecuted (ActionExecutedContext filtercontext) {             timer. Stop ();            if (filtercontext.exception = = null) {                 filterContext.HttpContext.Response.Write (                     string. Format ("<div>action method Elapsed Time: {0}</div>", timer. Elapsed.totalseconds));             }         }     

Add an action to the HomeController and apply the filter, as follows:

... [profileaction] public string filtertest () {     return ' This is the Actionfiltertest action ';} ...

Run the program, the URL is located to/home/filtertest, the result is as follows:

We see that the onactionexecuted method of Profileaction is performed before the Filtertest method returns the result. Specifically, the OnActionExecuted method is executed after the action method execution finishes and before the action returns the result.

The OnActionExecuting method and the OnActionExecuted method accept ActionExecutingContext and ActionExecutedContext object parameters respectively, These two parameters contain common properties such as Actiondescriptor, Canceled, exception, and so on.

Result Filter

The result filter is used to handle the results returned by the action method. The usage is similar to action filter, it needs to implement the Iresultfilter interface, which is defined as follows:

namespace SYSTEM.WEB.MVC {Public     interface Iresultfilter {         void onresultexecuting (ResultExecutingContext Filtercontext);         void onresultexecuted (ResultExecutedContext filtercontext);     

The Iresultfilter interface is similar to the previous Iactionfilter interface, and it is important to note that the result filter is executed after the action filter. The use of the two is the same, no longer speak more, directly to show example code.

Add a ProfileResultAttribute.cs class file under the Infrastructure folder with the following code:

public class Profileresultattribute:filterattribute, Iresultfilter {     private Stopwatch timer;     public void onresultexecuting (ResultExecutingContext filtercontext) {         timer = stopwatch.startnew ();     }     public void onresultexecuted (ResultExecutedContext filtercontext) {         timer. Stop ();         FilterContext.HttpContext.Response.Write (             string. Format ("<div>result Elapsed Time: {0}</div>",  timer. Elapsed.totalseconds));     } }

Apply the filter:

[Profileresult] public string filtertest () {     return ' This is the Actionfiltertest action ';} ...
Built-in Action and Result Filter

The MVC framework has a built-in ActionFilterAttribute class to create action and result filters that control the execution of the action method and also control the return result of the action method. It is an abstract class, defined as follows:

Public abstract class Actionfilterattribute:filterattribute, Iactionfilter, iresultfilter{public         virtual void OnActionExecuting (ActionExecutingContext filtercontext) {         } public         virtual void onactionexecuted ( ActionExecutedContext filtercontext) {         } public         virtual void onresultexecuting (ResultExecutingContext Filtercontext) {         } public         virtual void onresultexecuted (ResultExecutedContext filtercontext) {         }}     }

The convenience of using this abstract class is that you only need to implement methods that need to be addressed. Others are no different than using Iactionfilter and Iresultfilter interfaces. Here's a simple example.

Under the Infrastructure folder, add a ProfileAllAttribute.cs class file with the following code:

public class Profileallattribute:actionfilterattribute {     private Stopwatch timer;     public override void OnActionExecuting (ActionExecutingContext filtercontext) {         timer = stopwatch.startnew ();     } Public     override void Onresultexecuted (ResultExecutedContext filtercontext) {         timer. Stop ();         FilterContext.HttpContext.Response.Write (        string. Format ("<div>total Elapsed Time: {0}</div>",  timer. Elapsed.totalseconds));     } }

The filter is applied on the Filtertest method in HomeController:

public string Filtertest () {     return ' This is the Filtertest action ';} ...

Run the program, the URL navigates to/home/filtertest, and you can see the total amount of time that an action takes to complete the result before it is processed:

We can also directly override the four methods defined in the ActionFilterAttribute abstract class in the controller, with the same effect as using filter, for example:

public class Homecontroller:controller {     private Stopwatch timer;     ...    public string Filtertest () {         return ' This is the Filtertest action ';     }     protected override void OnActionExecuting (ActionExecutingContext filtercontext) {         timer = stopwatch.startnew ();     }     protected override void Onresultexecuted (ResultExecutedContext filtercontext) {         timer. Stop ();         FilterContext.HttpContext.Response.Write (             string. Format ("<div>total Elapsed Time: {0}</div>",             timer. Elapsed.totalseconds));     
Register as Global Filter

The global filter is valid for all action methods under all controllers of the entire application. In the App_start/filterconfig.cs file of the Registerglobalfilters method, you can register a filter class as a global, such as:

Using System.Web; Using SYSTEM.WEB.MVC; Using Mvcapplication1.infrastructure;  namespace MvcApplication1 {public     class Filterconfig {public         static void Registerglobalfilters ( Globalfiltercollection filters) {             filters. ADD (New Handleerrorattribute ());             filters. ADD (new  Profileallattribute ());         }     } }

We have added filters. ADD (New Profileallattribute ()) This line of code, where the filters parameter is a collection of globalfiltercollection types. In order to verify that Profileallattribute is applied to all actions, we create a new controller and add a simple action, as follows:

public class Customercontroller:controller {public         string Index () {             return ' This is the Customer Controller ';         } }

Run the program and locate the URL to/customer with the following results:

Other commonly used Filter

The MVC framework has a lot of filter built-in, Common Requirehttps, OutputCache, AsyncTimeout, and so on. The following examples illustrate several common ones.

    • Requirehttps, forcing access using the HTTPS protocol. It redirects the browser's request to the same controller and action, plus the https://prefix.
    • OutputCache, the output of the action method is cached.
    • Asynctimeout/noasynctimeout, the timeout setting for the asynchronous controller. (For the contents of the asynchronous controller, please visit xxxxxxxxxxxxxxxxxxxxxxxxxxx)
    • Childactiononlyattribute, using the action method can only be accessed by the Html.action and Html.renderaction methods.

Here we choose OutputCache This filter to do an example. Create a new Selectivecache controller with the following code:

public class Selectivecachecontroller:controller {public    actionresult Index () {         Response.Write ("Action Method is running: "+ DateTime.Now);         return View ();     }     [OutputCache (Duration =)]     Public ActionResult childaction () {         Response.Write ("Child action method is running:" + DateTime.Now);         return View ();     } }

Here Childaction applies the OutputCache filter, which is called within the view, and its parent action is index.

Now we create two view respectively, one is childaction.cshtml, the code is as follows:

@{     Layout = null;}  

The other is its index.cshtml, the code is as follows:

@{     viewbag.title = "Index";}  

Run the program, locate the URL to/selectivecache, and refresh it in a few seconds to see the following results:

ASP. Mvc-filter

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.