十四、理解Action Filter

这篇文章我们来讲述什么是Action Filter。Action Filter是一个可以贴在控制器或控制器动作上的特性标签,它用来指定该动作如何执行。在ASP.NET MVC框架中主要包含下面几个Action Filter:
OutputCache – 这个Action Filter用来把控制器的Action输出内容缓存指定长的时间。
HandleError – 这个Action Filter在action执行的时候处理异常信息。
Authorize – 这个Action Filter用来对指定的用户或角色授权。
我们还可以创建我们自己的Action Filter。如我们可以创建一个自定义的Action Filter来实现我们自己的身份验证系统,或者我们可以创建一个Action Filter修改控制器Action返回的ViewData数据。
在这篇文章中我们来学习如何从头来建造Action Filter。我们创建一个Log Action Filter用来在VS输出窗口中记录Action的执行过程。

一、使用Action Filter
Action Filter是一个可以贴在控制器或控制器动作上的特性标签。
像下面的DataController代码,我们创建一个名子为Index()的控制器动作,它返回当前时间。在这个动作上我们加上OutputCache Action Filter。这个Filter把Action返回的数据缓存10秒。
Listing 1 – Controllers\DataController.cs
using System;
using System.Web.Mvc;
namespace MvcApplication1.Controllers
{     
public class DataController : Controller     
{          
   [OutputCache(Duration=10)]          
   public string Index()          
   {               
    return DateTime.Now.ToString("T");          
   }     
}
}
如果我们在URL地址栏中重复输入/Data/Index去触发Index()动作,或连续点击工具栏中的“刷新”按钮,我们会发现在10秒钟之内页面上显示的是同样的时间,因为我们使用OutputCache Action Filter在Index()动作上加了10秒的缓存。
《图1》
上面的代码中,我们在Index()方法上面加入一个OutputCache Action Filter,我们还可以在同一个动作上加入多个Action Filter。比如,我们可以为同一个Action加上OutputCache和HandleError Action Filter。
上面的代码中,我们在Index()动作上加入了OutputCache Action Filter,我们还可以在DataController类上加入OutputCache Action Filter,这样在该控制器中的每个动作的输出数据都会缓存10秒钟。

 

二、不同类型的Filters (原创:灰灰虫的家http://hi.baidu.com/grayworm)
在ASP.NET MVC框架中包含以下四种不同类型的filters:
1. Authorization filters – 实现了IAuthorizationFilter接口的特性.
2. Action filters –实现了IActionFilter接口的特性.
3. Result filters –实现了IResultFilter接口的特性.
4. Exception filters –实现了IExceptionFilter接口的特性.
Filters是按照我们上面的顺序执行的。例如,Authorization filters总是在Action filters之前执行,Exception filters总是最后执行。

Authorization filters通常用来对控制器Actions进行身份验证和授权。

Action filters包含在控制器动作执行前和执行完要触发的逻辑。我们可以使用Action filter来修改控制器返回的ViewData
Result filters包含View Result执行前和执行完要触发的逻辑。例如我们要在视图呈现在浏览器之前修改View Result内容,那我们可以使用Result filter
Exception filter是最后运行的filter。我们可以使用Exception filter来处理控制器Action或控制器Action Results产生的异常信息。我们还可以使用Exception filter来记录错误信息。
对于不同类型的filter都有固定的执行顺序,不能更改。对于同一类filters,如果我们要控制它们的执行顺序,我们可以设置filter的Order属性进行调整。
所有动作的 Filters的基类都是System.Web.Mvc.FilterAttribute类。如果我们想实现特定类型的filter,那我们也需要创建一个派生自该类的类,并实现IAuthorizationFilter, IActionFilter, IResultFilter或 ExceptionFilter等接口中的一个或多个。

三、基类ActionFilterAttribute
为了能够轻松实现自定义的Action Filter,ASP.NET MVC框架包含一个ActionFilterAttribute基类。这个类实现了IActionFilter 和 IResultFilter接口并派生自FilterAttribute类
派生自ActionFilterAttribute的类即是Action Filter又是Result Filter。从一般意义上,我们把ASP.NET MVC框架中所有类型的filter称为action filter(动作过滤器)。
ActionFilterAttibute类有以下四个方法需要我们重写
OnActionExecuting –这个方法在控制器动作执行之前被调用.
OnActionExecuted – 这个方法在控制器动作执行之后被调用.
OnResultExecuting – 这个方法在Action Result执行之前被调用.
OnResultExecuted –这个方法在Action Result执行之后被调用.
下一部分中我们将看看如何实现这里面的方法

四、创建一个Log Action Filter (原创:灰灰虫的家http://hi.baidu.com/grayworm)
为了演示如何创建一个自定义的action filter, 我们创建一个自定义的action filter,用来在VS输出窗口中记录控制器动作的执行过程。LogActionFilter代码如下:
Listing 2 – ActionFilters\LogActionFilter.cs
using System;
using System.Diagnostics;
using System.Web.Mvc;
using System.Web.Routing;
namespace MvcApplication1.ActionFilters
{     
public class LogActionFilter : ActionFilterAttribute     
{          
   public override void OnActionExecuting(ActionExecutingContext filterContext)          
   {               
    Log("OnActionExecuting", filterContext.RouteData);          
   }          
   public override void OnActionExecuted(ActionExecutedContext filterContext)          
   {               
    Log("OnActionExecuted", filterContext.RouteData);          
   }          
   public override void OnResultExecuting(ResultExecutingContext filterContext)          
   {               
    Log("OnResultExecuting", filterContext.RouteData);          
   }          
   public override void OnResultExecuted(ResultExecutedContext filterContext)          
   {               
    Log("OnResultExecuted", filterContext.RouteData);          
   }          
   private void Log(string methodName, RouteData routeData)          
   {               
    var controllerName = routeData.Values["controller"];               
    var actionName = routeData.Values["action"];               
    var message = String.Format("{0} controller:{1} action:{2}", methodName, controllerName, actionName);               
    Debug.WriteLine(message, "Action Filter Log");          
   }     
}
}
在上面的代码中the OnActionExecuting(), OnActionExecuted(), OnResultExecuting()和 OnResultExecuted()方法调用了Log()方法。把当前的方法名和路由数据传递给Log()方法,而Log()方法就在VS输出窗口中输出信息。


《图2》
下面的代码演示了如何在HomeController上使用LogActionFilter过滤器。无论该控制器的哪个动作被触发,都会在VS输出窗口中显示动作的执行过程。
Listing 3 – Controllers\HomeController.cs
using System.Web.Mvc;
using MvcApplication1.ActionFilters;
namespace MvcApplication1.Controllers
{     
[LogActionFilter]     
public class HomeController : Controller     
{          
   public ActionResult Index()          
   {               
    return View();          
   }          
   public ActionResult About()          
   {               
    return View();          
   }     
}
}

总结
在这篇文章中,我们介绍了ASP。NET MVC的动作过滤器,我们知道有四种过滤器authorization filters, action filters, result filters和exception filters。我们还学习了ActionFilterAttribute类的知识。
最后我们学习了如何创建一个简单的自定义动作过滤器。我们创建了一个用来在VS输出窗口显示控制器动作过程的动作过滤器。

posted @ 2012-04-21 15:44  大智若简  阅读(729)  评论(0编辑  收藏  举报