有时候你想在调用action方法之前或者action方法之后处理一些逻辑,为了支持这个,ASP.NET MVC允许你创建action过滤器。Action过滤器是自定义的Attributes,用来标记添加Action方法之前或者Action方法之后的行为到控制器类中的Action方法中。

一些可能用到Action过滤器的地方有:

  • 日志,异常处理
  • 身份验证和授权 - 限制用户的访问
  • 输出缓存 - 保存一个Action的结果
  • 网络爬虫的过滤
  • 本地化
  • 动态Action - 将一个Action注入到控制器中

ASP.NET MVC为我们提供了下面的几个Filter接口:

    • IActionFilter
    • IAuthorizationFilter
    • IExceptionFilter
    • IResultFilter

      要实现一个Filter,我们需要继承自FilterAttribute类同时实现上面的一个或几个接口:

      public class MyFilter : FilterAttribute, IActionFilter, IResultFilter
      {

      这几个接口提供的方法如下:

      上图的方法和Filter接口对应的方法按名称对号入座就可以。

      IActionFilter接口有两个方法:

      其中OnActionExecuting在执行Action方法之前会被调用,OnActionExecuted会在Action方法执行后调用。注意他们的参数分别是ActionExecutingContext和ActionExecutedContext。

      ActionExecutedContext类包含一个 Canceled的属性,允许你取消当前的Action(怎么原来在P3中是在ActionExecutingContext的Canceled属性在P5中没有了呢?神奇.那么在OnActionExecuting的时候怎么取消一个Action呢?)。

      FilterExcutedContext 类包含一个Exception属性和一个ExceptionHandled属性。如果Exception属性为null,则没有异常在action stack中,表明Action方法运行并没有发生错误。反之则为出现异常。如果将ExceptionHandled属性设置为true则表明在这个Filter中已经处理了异常。

      IResultFilter接口也提供了两个方法:

      他们分别在Action返回结果(例如return View();)之前和之后执行。和IActionFilter差不多就不多说了。

      IAuthorizationFilter是一个用于身份验证的Filter。只提供了一个void OnAuthorization(AuthorizationContext filterContext)方法。

      IExceptionFilter会在出现异常的时候调用,也是只 提供一个void OnException(ExceptionContext filterContext)的方法;

      这些Filter可以被应用在类或者方法上,下面我们来看一下他们的执行顺序。首先我们写一个BaseController并加上两个Filter:

      [MyFilter2(Target = "BaseController")]
      [MyFilter1(Target="BaseController")]
      public class BaseController : Controller

      应为Controller类是实现这几个Filter接口的,所以我们在HomeController中重写Controller基类中的所有Filter接口的方法,并在HomeController类和里面的Filter方法加上我们自定义的MyFilter:

      [MyFilter2(Target = "HomeController")]
      //[MyFilter1(Target = "HomeController")]//注意我在这里把MyFilter1注释了.
      [HandleError]
      public class HomeController : BaseController
      {
          [MyFilter2(Target = "HomeController.Filter")]
          [MyFilter1(Target = "HomeController.Filter")]
          public ActionResult Filter()
          {
              return Content("<div>这是在Action方法里面返回的内容!</div>");
          }      protected override void OnActionExecuted(ActionExecutedContext filterContext)
          {
              filterContext.HttpContext.Response.Write("<div>这是在HomeController里面重写OnActionExecuted方法添加的内容!</div>");
          }      protected override void OnActionExecuting(ActionExecutingContext filterContext)
          {
              filterContext.HttpContext.Response.Write("<div>这是在HomeController里面重写OnActionExecuting方法添加的内容!</div>");
          }      protected override void OnAuthorization(AuthorizationContext filterContext)
          {
              filterContext.HttpContext.Response.Write("<div>这是在HomeController里面重写OnAuthorization方法添加的内容!</div>");
          }      protected override void OnException(ExceptionContext filterContext)
          {
              filterContext.HttpContext.Response.Write("<div>这是在HomeController里面重写OnException方法添加的内容!</div>");
              filterContext.ExceptionHandled = true;
          }      protected override void OnResultExecuted(ResultExecutedContext filterContext)
          {
              filterContext.HttpContext.Response.Write("<div>这是在HomeController里面重写OnResultExecuted方法添加的内容!</div>");
          }      protected override void OnResultExecuting(ResultExecutingContext filterContext)
          {
              filterContext.HttpContext.Response.Write("<div>这是在HomeController里面重写OnResultExecuting方法添加的内容!</div>");
          }

      然后我们运行一下看看结果如何:

      从运行结果我们可以看到,在Controller中重写的Filter会最先执行,然后到应用在类上的Filter,然后再到应用在类方法上的Filter。

      而4个接口的方法执行顺序如下:IAuthorizationFilter -> IActionFilter -> IResultFilter -> IExceptionFilter .

      而对于同一个Filter,例如IAuthorizationFilter在MyFilter1和MyFilter2里里面的实现,又根据他们的加载顺序不同而不同。

      在BaseController中应用的Filter会被子类继承,如果子类又应用了和基类同样的Filter,则会不执行基类的Filter。例如上面的HomeController应用了MyFilter2,所以调用HomeController的MyFilter2,而不是BaseController的MyFilter2。

      这个执行顺序还得大家好好研究才能了解的。

      同时FilterAttribute还提供了一个Order的属性,用于指定Filter的执行顺序。

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

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

      来看一个示例:

      
      [Filter1(Order = 2)]
      [Filter2(Order = 3)]
      [Filter3(Order = 1)]
      public void Index()
      {
          RenderView("Index");

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

      暂时就写这么多吧,这一部分主要介绍概念。Enjoy!Post by Q.Lee.lulu

      本文的Blog程序示例代码: ActionFilter.rar

[转]ASP.NET MVC 入门9、Action Filter 与 内置的Filter实现(介绍)的更多相关文章

  1. ASP.NET MVC 入门10、Action Filter 与 内置的Filter实现(实例-防盗链)

    于ASP.NET MVC Preview5. 前一篇中我们已经了解了Action Filter 与 内置的Filter实现,现在我们就来写一个实例.就写一个防盗链的Filter吧. 首先继承自Filt ...

  2. [转]ASP.NET MVC 入门10、Action Filter 与 内置的Filter实现(实例-防盗链)

    前一篇中我们已经了解了Action Filter 与 内置的Filter实现,现在我们就来写一个实例.就写一个防盗链的Filter吧. 首先继承自FilterAttribute类同时实现IAction ...

  3. ASP.NET MVC 入门9、Action Filter 与 内置的Filter实现(介绍)

    原帖地址:http://www.cnblogs.com/QLeelulu/archive/2008/10/09/1307660.html 有时候你想在调用action方法之前或者action方法之后处 ...

  4. ASP.NET MVC 入门系列教程

    ASP.NET MVC 入门系列教程 博客园ASP.NET MVC 技术专题 http://kb.cnblogs.com/zt/mvc/ 一个居于ASP.NET MVC Beta的系列入门文章,有朋友 ...

  5. 10、ASP.NET MVC入门到精通——Model(模型)和验证

    本系列目录:ASP.NET MVC4入门到精通系列目录汇总 模型就是处理业务,想要保存.创建.更新.删除的对象. 注解(通过特性实现) DisplayName Required StringLengt ...

  6. ASP.NET MVC 入门8、ModelState与数据验证

    原帖地址:http://www.cnblogs.com/QLeelulu/archive/2008/10/08/1305962.html ViewData有一个ModelState的属性,这是一个类型 ...

  7. ASP.NET MVC内置的Filter实现介绍

    有时候你想在调用action方法之前或者action方法之后处理一些逻辑,为了支持这个,ASP.NET MVC允许你创建action过滤器.Action过滤器是自定义的Attributes,用来标记添 ...

  8. [转]ASP.NET MVC 入门8、ModelState与数据验证

    ViewData有一个ModelState的属性,这是一个类型为ModelStateDictionary的ModelState类型的字典集合.在进行数据验证的时候这个属性是比较有用的.在使用Html. ...

  9. ASP.NET MVC 入门

    ASP.NET MVC 入门 (Learning ASP.NET MVC) 传统的WebForm发展到如今出现不少的缺陷, 比如为了解决Http的无状态WebForm模式使用了ViewsState来保 ...

随机推荐

  1. Git 安装与使用(一)

    一.简介 1.集中式版本控制系统(CVS):Svn     * 版本库是集中存放在中央服务器中的,客户端需要先从中央服务器取得最新的版本,然后再干活,活干完后,再把自己的代码推送给中央服务器.    ...

  2. sql server 2008数据复制方法

    发布订阅份为两个步骤:1.发布.2.订阅.首先在数据源数据库服务器上对需要同步的数据进行发布,然后在目标数据库服务器上对上述发布进行订阅.发布可以发布一张表的部分数据,也可以对整张表进行发布.下面分别 ...

  3. PHP中0、空、null和false的总结

    php中很多人还不懂php中 0 , '' , null 和 false 之间的区别,这些区别有时会影响到数据判断的正确性和安全性,给程序的测试运行造成很多麻烦.另外在面试题中也会遇到这些问题,如下: ...

  4. [CSS]font- 属性

    所有浏览器都支持 font 属性. 注释:任何的版本的 Internet Explorer (包括 IE8)都不支持属性值 "inherit". 定义和用法 font 简写属性在一 ...

  5. web2py--------------用web2py写 django的例子 --------开发环境

    我们先从广为人知的例子说起xi 也就是官方的例子,我会在最后给出代码: ============================环境=================== 编译器使用vs code , ...

  6. leetcode解题—Longest Palindromic Substring

    题目: Given a string S, find the longest palindromic substring in S. You may assume that the maximum l ...

  7. Python设计模式——状体模式

    需求,根据当前的时间,返回工作状态 #encoding=utf-8 __author__ = 'kevinlu1010@qq.com' def get_state(hour): if hour> ...

  8. Anagrams问题

    #include<stdio.h> #include<string.h> int main() { int i; ],word2[]; //分别用于存储输入的两个单词 int ...

  9. Render Texture的使用(截取rendertexture的一帧到Texture2D)

    游戏里人物角色太多,每个角色都要有张头像或全身照等,这样就必须截取大量的图片,花费大量的时间,有时截取的不满意还得重新截,即浪费时间又浪费精力.所以就想了个投机取巧的方法.那就是用unity搭建一个照 ...

  10. Lucene基础(三)-- 中文分词及高亮显示

    Lucene分词器及高亮 分词器 在lucene中我们按照分词方式把文档进行索引,不同的分词器索引的效果不太一样,之前的例子使用的都是标准分词器,对于英文的效果很好,但是中文分词效果就不怎么样,他会按 ...