我来说说MVC过滤器

APS.NET MVC中的每一个请求,都会分配给相应的控制器和对应的行为方法去处理,而在这些处理的前前后后如果想再加一些额外的逻辑处理。这时候就用到了过滤器。

在Asp.netMvc中当你有以下及类似以下需求时你可以使用Filter功能

 

  1. 判断登录与否或用户权限
  2. 决策输出缓存
  3. 防盗链
  4. 防蜘蛛
  5. 本地化与国际化设置
  6. 实现动态Action

 

MVC支持的过滤器类型有四种,分别是:Authorization(授权),Action(行为),Result(结果)和Exception(异常)。

如下表

 

过滤器类型

接口

描述

Authorization

IAuthorizationFilter

此类型(或过滤器)用于限制进入控制器或控制器的某个行为方法

Exception

IExceptionFilter

用于指定一个行为,这个被指定的行为处理某个行为方法或某个控制器里面抛出的异常

Action

IActionFilter

用于进入行为之前或之后的处理

Result

IResultFilter

用于返回结果的之前或之后的处理

 

但是默认实现它们的过滤器只有三种,分别是Authorize(授权),ActionFilter,HandleError(错误处理);各种信息如下表所示

 

过滤器

类名

实现接口

描述

ActionFilter

AuthorizeAttribute

IAuthorizationFilter

此类型(或过滤器)用于限制进入控制器或控制器的某个行为方法

HandleError

HandleErrorAttribute

IExceptionFilter

用于指定一个行为,这个被指定的行为处理某个行为方法或某个控制器里面抛出的异常

自定义

ActionFilterAttribute

IActionFilter和IResultFilter

用于进入行为之前或之后的处理或返回结果的之前或之后的处理

 

一、应用于Action的Filter

创建 Action filter 必须实现 IActionFilter 接口,该接口定义了两个方法

 

方法名 调用时机 可进行的操作
OnActionExecuting Action方法执行之前 可以给 filterContext.Result 赋值,以阻止 Action 的执行
可以通过 filterContext.ActionParameters 查看或修改 Action 的参数
OnActionExecuted Action方法执行之后 可以通过 filterContext.Exception 获取 Action 执行时抛出的异常,并能把它标记为“已处理”:filterContext.ExceptionHandled = true。
可以查看通过filterContext.Result查看 Action 的执行结果,但是不能修改。

 

Action过滤器是通过继承ActionFilterAttribute类来实现的一个Attribute类。ActionFilterAttribute 是一个抽象类,提供了两个virtual的方法给我们重写,OnActionExecutingOnActionExecuted

ASP.NET MVC 框架会在调用Action方法之前调用你Action过滤器中的OnActionExecuting方法,在之后调用Action过滤器中的OnActionExecuted方法。当然在创建Action过滤器的时候你不需两个方法都实现。

 

下面的示例是在调用Action方法之前和之后的日志跟踪:

 
C# 代码   复制

public class LoggingFilterAttribute : ActionFilterAttribute
 {
     public override void OnActionExecuting(FilterExecutingContext 
        filterContext)
     {
         filterContext.HttpContext.Trace.Write("Starting: " + 
         filterContext.ActionMethod.Name);
     } 
 
    public override void OnActionExecuted(FilterExecutedContext 
        filterContext)
     {
         if (filterContext.Exception != null)
         {
             filterContext.HttpContext.Trace.Write("Exception thrown");
         }
     }
 }

 

部分参数说明

 

Action Filter Context

OnActionExecuting方法有一个类型为FilterExecutingContext的参数,而OnActionExecuted方法有一个相应的类型为FilterExcutedContext的参数。两个Context类都是继承自FilterContext类,而FilterContext类继承自ControllerContext类并包含一个ActionMethod属性。你可以使用ActionMethod属性来坚定这个Action过滤器是应用到哪个Action方法上的。

FilterExecutingContext类包含一个 Cancel 的属性,允许你取消当前的Action。

FilterExcutedContext 类包含一个Exception属性和一个ExceptionHandled属性。如果Exception属性为null,则没有异常在action stack中,表明Action方法运行并没有发生错误。如果Exception属性不为null,则过滤器知道该怎么处理,过滤器处理完异常后会发出已经处理完的信号,然后将ExceptionHandled属性设为true。就算ExceptionHandled属性为true,堆栈中添加到其他Action方法的OnActionExcetued方法将会照常被调用,这种场景就如就算一个异常被处理了,日志记录filter一样照常执行。

 

使用方法

你可以将过滤器应用到任何一个你喜欢的Action方法上。下面的示例演示一个控制器中包含的用Action过滤器Attribute标记的Action方法。

 
C# 代码   复制

public class HomeController : Controller
 {
     [LoggingFilter]
     public void Index()
     {
         RenderView("Index");
     } 
 
    [LoggingFilter]
     public void About()
     {
         RenderView("About");
     } 
 
    [LoggingFilter]
     public void ClickMe()
     {
         HttpContext.Trace.Write("Button was clicked.");
         InvokeAction("Index");
     }
 }

 

Action过滤器的作用范围

除了用Action过滤器标记一个Action方法外,你也可以用来标记一个完成的控制器类。如果这样的话,这个Action过滤器将会应用到该控制器的所有Action方法上。

另外,如果你的控制器类继承自别的控制器类,而基控制器类可能有它自己的Action过滤器Attributes。如果你在子类中重写了基控制器类的Action方法,则子类的该Action方法也会有它自己的从基类继承而来的Action过滤器Attributes。

 

Action过滤器的执行顺序

每一个Action过滤器都有一个 Order 属性,用来决定Action过滤器在该范围内的执行顺序。Order属性必需是0(默认值)或者更大的整数值。省略Order属性则会给该过滤器的Order值为 -1, 表明为指明顺序。任何一个在同一范围的Action过滤器Order设为 -1 的都将按不确定的顺序执行,单在此之前过滤器有一个特定的顺序(注:下面会说到).

当设置Order属性的值的时候,必需指定一个唯一的值。如果两个或者更多的Action过滤器具有相同的Order属性值,将会抛出一个异常。

示例:

 
C# 代码   复制
 
 [Filter1(Order = 2)]
 [Filter2(Order = 3)]
 [Filter3(Order = 1)]
 public void Index()
 {
     RenderView("Index");
 }

Filter的执行顺序为:Filter3 => Filter1 => Filter2.

 

二、Controller的Filter

 

ASP.NET MVC 控制器(Controller)类定义的OnActionExecuting 和 OnActionExcuted 方法你可以重写。当你重写一个或者这两个方法的时候,你实际上定义了一个将会应用到该控制器类中所有的Action方法的Action过滤器。严格来说,这个方法没有构成一个Action过滤器,但不管怎样,她们提供的功能是相似的。

 

将Filter应用在Controller上有2种方式

1.直接将Filter应用在Controller上,如:

    [TestFilter]
    public class EiceController : Controller
    {
     }

 

2.重写Controller内的


OnActionExecuting/OnActionExecuted/OnResultExecuting/OnResultExecuted的四个方法。

 

在下面的示例中,控制器级别的OnActionExecuting和OnActionExecuted方法应用到控制器中所有的Action方法中:

 
C# 代码   复制

public class HomeController : Controller
 {
     public void Index()
     {
         RenderView("Index");
     }
 
    public void About()
     {
         RenderView("About");
     }
 
    public void ClickMe()
     {
         HttpContext.Trace.Write("Button was clicked.");
         InvokeAction("Index");
     }
 
    protected override void OnActionExecuting(FilterExecutingContext 
        filterContext)
     {
         filterContext.HttpContext.Trace.Write("Starting: " + 
             filterContext.ActionMethod.Name);
     }
 
    protected override void OnActionExecuted(FilterExecutedContext 
        filterContext)
     {
         if (filterContext.Exception != null)
         {
             filterContext.HttpContext.Trace.Write("Exception thrown");
         }
     }
 }

 

三、几个系统常用的Filter过滤器

 

1、AcceptVerbs

规定页面的访问形式,如

        [AcceptVerbs(HttpVerbs.Post)]
         public ActionResult Example(){
             return View();
         }


页面只能以Post形式访问,即表单提交。

 

2、ActionName

规定Action的名称。

应用场景:如果不想用方法名做为Action名,或Action名为关键字的话,如

       [ActionName("class")]
         public ActionResult Example(){
             return View();
         }

 

3、NonAction

当前方法仅是普通方法不解析为Action

 

4、OutputCache

为Action添加缓存

        [OutputCache(Duration = 60, VaryByParam = "*")]
        public ActionResult Example()
        {
            return View();
        }

 

5、ValidateInput

该Action可以接受Html等危险代码(ASP.NET MVC在aspx中设置<%@ Page 的属性无法完成等同任务。)

        [ValidateInput(false)]
        public ActionResult Example()
        {
            return View();
        }

 

6、ValidateAntiForgeryTokenAttribute

用于验证服务器篡改。

        [ValidateAntiForgeryToken]
        public ActionResult Example()
        {
            return View();
        }

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。