由于工作需要,最近在学习ASP.NET MVC3,感觉Filter在以后的应用中不能说必不可少,只能说感觉会让我们在写程序的时候对于一些经常要处理的并且统一处理的事情上能达到事半功倍的效果,因此在这里记录一下学习到的内容。有不对的地方,还需要各位指出。
在ASP.NET MVC3中,给我个人感觉最大的特点就是运用的attribute(我个人理解为标记)是比较多的,而且attribute能让我们更容易的去调用我们自定义逻辑处理的标记或者是调用系统自带的一些标记,让我们的代码更简洁。在本节中,我们还是主要看下Filter给我们程序带来的好处。
在ASP.NET MVC 框架中,为我们提供了四种类型的Filter类型包括:IAuthorizationFilter、IActionFilter、IResultFilter、IExceptionFilter,执行顺序如下:
- IAuthorizationFilter 最先执行的,在这些Filter中,我们可以说它的执行优先级是最高的,用于身份验证并对控制器中的action进行授等进行逻辑处理
- IActionFilter 在IAuthorizationFilter之后执行,包含两个方法,在controller中的action执行之前、执行之后进行逻辑处理
- IResultFilter 同样包含两个方法,在IActionFilter之后执行,在返回View之前和返回View之后执行逻辑处理
- IException 主要用于对异常信息进行处理
通过上述信息我们可以看到各个Filter之间运行的顺序。在我们要对程序运行时候的这四个阶段进行特殊处理的时候,我们可以自己写一个Filter类去实现其中的逻辑处理代码,实现相应的接口就可以进行特殊处理。ASP.NET MVC框架为我们提供了一个抽象类,名为:ActionFilterAttribute,这个抽象类只实现了IActionFilter和IResultFilter这两个接口中的方法,分别是:IActionFilter(OnActionExcuting、OnActionExcuted)、IResultFilter(OnResultExcuting、OnResultExcuted)。如果需要对验证或者异常进行特殊处理的话,还是需要实现IAuthorizationFilter或IException。
下面写一个实现自定义Filter的非常简单的例子,来更好的记住Filter的执行顺序,代码如下:
Filter:
public class OwnActionFilter : ActionFilterAttribute { /// <summary> /// 在action method之前执行 /// </summary> /// <param name="filterContext"></param> public override void OnActionExecuting(ActionExecutingContext filterContext) { filterContext.HttpContext.Response.Write("方法名称:OnActionExecuting<br/>"); //输出请求的控制器与action名称 String controllerName = filterContext.RouteData.Values["controller"].ToString(); String actionName = filterContext.RouteData.Values["action"].ToString(); String message = String.Format("控制器:{0}<br/>action:{1}<br/>", controllerName, actionName); filterContext.HttpContext.Response.Write(message); filterContext.HttpContext.Response.Write("------------------华丽的分割线------------------<br>"); } /// <summary> /// 在action method之后执行 /// </summary> /// <param name="filterContext"></param> public override void OnActionExecuted(ActionExecutedContext filterContext) { filterContext.HttpContext.Response.Write("方法名称:OnActionExecuted<br/>"); //输出请求的控制器与action名称 String controllerName = filterContext.RouteData.Values["controller"].ToString(); String actionName = filterContext.RouteData.Values["action"].ToString(); String message = String.Format("控制器:{0}<br/>action:{1}<br/>", controllerName, actionName); filterContext.HttpContext.Response.Write(message); filterContext.HttpContext.Response.Write("------------------华丽的分割线------------------<br/>"); } /// <summary> /// 在返回view之前执行 /// </summary> /// <param name="filterContext"></param> public override void OnResultExecuting(ResultExecutingContext filterContext) { filterContext.HttpContext.Response.Write("方法名称:OnResultExecuting<br/>"); //输出请求的控制器与action名称 String controllerName = filterContext.RouteData.Values["controller"].ToString(); String actionName = filterContext.RouteData.Values["action"].ToString(); String message = String.Format("控制器:{0}<br/>action:{1}<br/>", controllerName, actionName); filterContext.HttpContext.Response.Write(message); filterContext.HttpContext.Response.Write("------------------华丽的分割线------------------<br/>"); } /// <summary> /// 在返回View之后执行 /// </summary> /// <param name="filterContext"></param> public override void OnResultExecuted(ResultExecutedContext filterContext) { filterContext.HttpContext.Response.Write("方法名称:OnResultExecuted<br/>"); //输出请求的控制器与action名称 String controllerName = filterContext.RouteData.Values["controller"].ToString(); String actionName = filterContext.RouteData.Values["action"].ToString(); String message = String.Format("控制器:{0}<br/>action:{1}<br/>", controllerName, actionName); filterContext.HttpContext.Response.Write(message); filterContext.HttpContext.Response.Write("------------------华丽的分割线------------------<br/>"); } }
上面为自定义Filter,便于大家看到信息,我直接输出到浏览器,其中包括方法名、控制器名称与action名称。在这里大家应该可以看到在ResultExcutedContex、ActionExecutingContext这两个类型,他们都集成自ControllerContext,因此,它们一样可以拿到HttpMethod、Session等一系列我们在ASPX中经常用到的一些信息。下面为Controller的代码:
Controller:
public class FilterController : Controller { // // GET: /Filter/ [OwnActionFilter] public ActionResult Index() { ViewBag.DateTime = "Index View"; return View(); } }
大家可以看到,在Index方法前,我加入了OwnActionFilter的attribute(标记),那么当Index方法执行的时候,就会执行我们自己定义的Filter类中的方法。那么看一下我们自定义Filter的执行顺序吧,效果如下图:
为了便于看到执行的顺序,我把Index View进行了加粗:)通过上图,我们可以看到IActionFilter、IResultFilter执行的顺序。那么,前面已经说了,IAuthorizationFilter是在IActionFilter、IResultFilter之前运行的,那么我们把IAuthorizationFilter接口实现(为了节约篇幅,一并加入IException接口并给予实现)代码如下:
Filter:
public class OwnActionFilter : ActionFilterAttribute,IAuthorizationFilter,IExceptionFilter { /// <summary> /// 最先执行 /// </summary> /// <param name="filterContext"></param> public void OnAuthorization(AuthorizationContext filterContext) { filterContext.HttpContext.Response.Write("方法名称:OnAuthorization<br/>"); //输出请求的控制器与action名称 String controllerName = filterContext.RouteData.Values["controller"].ToString(); String actionName = filterContext.RouteData.Values["action"].ToString(); String message = String.Format("控制器:{0}<br/>action:{1}<br/>", controllerName, actionName); filterContext.HttpContext.Response.Write(message); filterContext.HttpContext.Response.Write("------------------华丽的分割线------------------<br/>"); } /// <summary> /// 在action method之前执行 /// </summary> /// <param name="filterContext"></param> public override void OnActionExecuting(ActionExecutingContext filterContext) { filterContext.HttpContext.Response.Write("方法名称:OnActionExecuting<br/>"); //输出请求的控制器与action名称 String controllerName = filterContext.RouteData.Values["controller"].ToString(); String actionName = filterContext.RouteData.Values["action"].ToString(); String message = String.Format("控制器:{0}<br/>action:{1}<br/>", controllerName, actionName); filterContext.HttpContext.Response.Write(message); filterContext.HttpContext.Response.Write("------------------华丽的分割线------------------<br>"); } /// <summary> /// 在action method之后执行 /// </summary> /// <param name="filterContext"></param> public override void OnActionExecuted(ActionExecutedContext filterContext) { filterContext.HttpContext.Response.Write("方法名称:OnActionExecuted<br/>"); //输出请求的控制器与action名称 String controllerName = filterContext.RouteData.Values["controller"].ToString(); String actionName = filterContext.RouteData.Values["action"].ToString(); String message = String.Format("控制器:{0}<br/>action:{1}<br/>", controllerName, actionName); filterContext.HttpContext.Response.Write(message); filterContext.HttpContext.Response.Write("------------------华丽的分割线------------------<br/>"); } /// <summary> /// 在返回view之前执行 /// </summary> /// <param name="filterContext"></param> public override void OnResultExecuting(ResultExecutingContext filterContext) { filterContext.HttpContext.Response.Write("方法名称:OnResultExecuting<br/>"); //输出请求的控制器与action名称 String controllerName = filterContext.RouteData.Values["controller"].ToString(); String actionName = filterContext.RouteData.Values["action"].ToString(); String message = String.Format("控制器:{0}<br/>action:{1}<br/>", controllerName, actionName); filterContext.HttpContext.Response.Write(message); filterContext.HttpContext.Response.Write("------------------华丽的分割线------------------<br/>"); } /// <summary> /// 在返回View之后执行 /// </summary> /// <param name="filterContext"></param> public override void OnResultExecuted(ResultExecutedContext filterContext) { filterContext.HttpContext.Response.Write("方法名称:OnResultExecuted<br/>"); //输出请求的控制器与action名称 String controllerName = filterContext.RouteData.Values["controller"].ToString(); String actionName = filterContext.RouteData.Values["action"].ToString(); String message = String.Format("控制器:{0}<br/>action:{1}<br/>", controllerName, actionName); filterContext.HttpContext.Response.Write(message); filterContext.HttpContext.Response.Write("------------------华丽的分割线------------------<br/>"); } /// <summary> /// 当出现异常时才执行 /// </summary> /// <param name="filterContext"></param> public void OnException(ExceptionContext filterContext) { filterContext.HttpContext.Response.Write("方法名称:OnException<br/>"); //输出请求的控制器与action名称 String controllerName = filterContext.RouteData.Values["controller"].ToString(); String actionName = filterContext.RouteData.Values["action"].ToString(); String message = String.Format("控制器:{0}<br/>action:{1}", controllerName, actionName); filterContext.HttpContext.Response.Write(message); filterContext.HttpContext.Response.Write("------------------华丽的分割线------------------<br/>"); } }
执行之后,效果如下图:
通过上图我们可以看到,OnAuthorization方法,是在所有方法(IActionFilter、IResultFilter)之前进行执行的,那么唯一没有执行的是IException接口的OnException方法。这个方法是当我们的应用程序中出现错误的时候才执行的。以便我们统一对错误进行处理。
以上为我对ASP.NET MVC3中的Filter的理解,共享给大家,如果有什么不对的地方,也希望大家留言提出,也希望大家能留言一起讨论。