上一篇讲到ActionFilter
,这一篇我们来讲解ResultFilter
,顾名思义,就是结果过滤器。和ActionFilter
要实现抽象类ActionFilterAttribute
里面的四个方法一样,我们自定义的ResultFilter
的过滤特性类也要继承ActionFilterAttribute
才行,同时实现接口IResultFilter
里面的方法:
public interface IResultFilter {
void OnResultExecuting(ResultExecutingContext filterContext);
void OnResultExecuted(ResultExecutedContext filterContext);
}
OnResultExecuting
是在动作结果执行之前执行,OnResultExecuted
是在动作结果之后执行,什么是动作结果?我们可以这样来理解,Action
就是一个动作,这个动作的结果是可能会返回一个ViewResult
渲染到浏览器中,在整个Action
的生命周期之内成为Action
的执行,之前执行OnActionExecuting
,之后执行OnResultExecuted
方法,那OnActionExecuted
方法和OnResultExecuting
方法在什么时候执行呢,答案是在Action
之后,Result
之前。我们来看一个的demo
吧:
我们定义一个MyTestResultFiter
,让他继承自ActionFilterAttribute
类,具体实现如下:
public class MyTestResultFiter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.HttpContext.Response.Write("OnActionExecuting方法:
");
base.OnActionExecuted(filterContext);
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
filterContext.HttpContext.Response.Write("OnActionExecuted方法
");
base.OnActionExecuted(filterContext);
}
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
filterContext.HttpContext.Response.Write("OnResultExecuting方法:
");
base.OnResultExecuting(filterContext);
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
filterContext.HttpContext.Response.Write("OnResultExecuted方法:
");
base.OnResultExecuted(filterContext);
}
同时我们创建一个MVC
的项目,创建一个MyResultFilter
控制器,具体如下:
public class MyResultFilterController : Controller
{
[MyTestResultFiter]
public ActionResult Index()
{
Response.Write("这里执行是Action方法,非ViewResult
");
return View();
}
}
Index
的视图如下:
@{Layout = null; }
<html> <head> <title>Indextitle> head>
<body><div>
<p>ViewResult:这里是Result的首页哦~~~~~~p>
div> body>
html>
OnActionExecuting
方法和OnResultExecuted
方法的执行顺序无可争议,问题在于Action
里面Response.Write
的内容是先于OnActionExecuted
方法执行的,因此我们可以断定:OnActionExecuted
方法的执行时间实在Action
的生命周期之后执行的,Action
的生命周期说白了就是大括号{}
里面的代码,OnResultExecuting
方法实在动作结果之前执行,我们的示例中动作结果输出的是Index
这个视图,因此会看到OnResultExecuted
实在ViewResult
之后执行。上图中示例执行顺序
OnActionExecuting>Action>OnActionExecuted>OnResultExecuting>ViewResult>OnResultExecuted。
但是如果只有动作结果过滤器来过滤请求的话,标签要在每一个动作上做上标签,显然是不符合软件的设计思想的,mvc
好在为我们提供了一个全局的过滤器,全局过滤器我们需要在全局文件Global.asax
中进行注册,我们按照刚才的例子稍加改进一下,来看具体的结果。
在Global.asax
中注册全局过滤器:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new MyTestResultFiter() { FilterMessage="标志全局过滤器"});
}
同时将MyTestResultFiter
过滤器稍作修改如下:
[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
public class MyTestResultFiter : ActionFilterAttribute
{
public string FilterMessage
{
get;
set;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.HttpContext.Response.Write("OnActionExecuting方法:" + FilterMessage + "
");
base.OnActionExecuting(filterContext);
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
filterContext.HttpContext.Response.Write("OnActionExecuted方法" + FilterMessage + "
");
base.OnActionExecuted(filterContext);
}
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
filterContext.HttpContext.Response.Write("OnResultExecuting方法" + FilterMessage + "
");
base.OnResultExecuting(filterContext);
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
filterContext.HttpContext.Response.Write("OnResultExecuted方法" + FilterMessage + "
");
base.OnResultExecuted(filterContext);
}
}
同时注意将MyTestResultFiter
标注为AllowMultiple = true
,这样MyTestResultFiter
就可以执行在Controller
和Action
上都起作用。否则执行执行Action
上的MyTestResultFiter
特性。运行结果如下:
但是还有一点我们需要注意的是Controller
它本身也是一个过滤器,我们来看Controller
的定义:
public abstract class Controller : ControllerBase, IActionFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter
Controller
也实现了mvc
的四大过滤器的接口,因此我们来测试一下这个Controller
过滤器的执行顺序是什么?我们在MyResultFilter
里面稍作修改:
[MyTestResultFiter(FilterMessage="这里是Controller的:")]
public class MyResultFilterController : Controller
{
[MyTestResultFiter(FilterMessage = "这里是Action的:")]
public ActionResult Index()
{
Response.Write("这里执行是Action方法,非ViewResult
");
return View();
}
}
因此整个过滤器的执行顺序大致如下:全局过滤器>Controller上标记的特性过滤器>Action上标记的特性过滤器
,里面的四种方法的执行顺序大家看完之后应该明白了吧~~~