在开发大项目的时候总会有相关的AOP面向切面编程的组件,而MVC(特指:Asp.Net MVC,如下皆同)项目中不想让MVC开发人员去关心和写相似身份验证,日志,异常,行为截取等这部分重复的代码,那咱们能够经过AOP截取实现,而在MVC项目中咱们就能够直接使用它提供的Filter的特性帮咱们解决,不用本身实现复杂的AOP了。编程
在Asp.net Mvc中当你有如下及相似如下需求时你可使用Filter功能浏览器
Asp.Net MVC提供了如下几种默认的Filter:缓存
Filter Type服务器
实现接口ide
执行时间字体
Default Implementationui
Authorization filter.net
IAuthorizationFilter3d
在全部Filter和Action执行以前执行日志
AuthorizeAttribute
Action filter
IActionFilter
分别在Action执行以前和以后执行。
ActionFilterAttribute
Result filter
IResultFilter
分别在Action Result执行以后和以前
ResultFilterAttribute
Exception filter
IExceptionFilter
只有在filter,
或者 action method, 或者 action result 抛出一个异常时候执行
HandleErrorAttribute
你们注意一点,Asp.Net MVC提供的ActionFilterAttribute默认实现了IActionFilter和IResultFilter。而ActionFilterAttribute是一个Abstract的类型,因此不能直接使用,由于它不能实例化,因此咱们想使用它必须继承一下它而后才能使用。
Filter继承于ActionFilterAttribute抽象类,并能够覆写 void OnActionExecuting(ActionExecutingContext) 和 voidOnActionExecuted(ActionExecutedContext) 以及 void OnResultExecuting(ResultExecutingContext)和 voidOnResultExecuted(ResultExecutedContext)。
它们的执行前后顺序以下:
OnActionExecuting是Action执行前的操做
OnActionExecuted则是Action执行后的操做
OnResultExecuting是解析ActionResult前执行
OnResultExecuted是解析ActionResult后执行
接下来咱们只要对以上的方法进行重写就能够在相应的步骤作一些操做了。
光说不练假把式,下面我给你们一个示例,来看看它们的执行顺序
首先添加一个普通的类,这个类要继承ActionFilterAttribute,,直接上代码了
public class TestFilterAttribute:ActionFilterAttribute { public string Message { get; set; } public override void OnActionExecuting(ActionExecutingContext filterContext) { base.OnActionExecuting(filterContext); filterContext.HttpContext.Response.Write("Action执行以前"+Message+"<br />"); } public override void OnActionExecuted(ActionExecutedContext filterContext) { base.OnActionExecuted(filterContext); filterContext.HttpContext.Response.Write("Action执行以后"+Message+"<br />"); } public override void OnResultExecuting(ResultExecutingContext filterContext) { base.OnResultExecuting(filterContext); filterContext.HttpContext.Response.Write("返回Result以前"+Message+"<br />"); } public override void OnResultExecuted(ResultExecutedContext filterContext) { base.OnResultExecuted(filterContext); filterContext.HttpContext.Response.Write("返回Result以后"+Message+"<br />"); } }
写完这个代码后,咱们回到Action上,打上上面的标记以下所示:
[TestFilter(Message="Action")] public ActionResult Index() { HttpContext.Response.Write("Action正在执行···<br />"); return Content("正在返回Result···<br />"); }
而后经过浏览器访问上面的Action即可以看到下面的执行顺序
总的执行顺序是:
Action执行前:OnActionExecuting方法先执行→Action执行→OnActionExecuted方法执行→OnResultExecuting方法执行→返回的ActionRsult中的executeResult方法执行→OnResultExecuted执行。最终显示的效果就是如上图所示。
感受很爽吧!呵呵!这要想用到这个过滤机制的地方的时候,只要在Action上面添加标记即可以实现效果。
若是咱们将此标签打到Controller上的话,TestFilterAttributeFilter将做用到Controller下的全部的Action。例如以下代码所示:
[TestFilter(Message="Controller")] public class TestFilterController : Controller { // // GET: /TestFilter/ [TestFilter(Message="Action")] public ActionResult Index() { HttpContext.Response.Write("Action正在执行···<br />"); return Content("正在返回Result···<br />"); } }
若是单纯的按照上面的代码来作就有个问题了咱们再执行显示的页面会有什么状况呢?Controller上的Filter会执行吗?那标签的做用会执行两次吗?下面是最后的执行结果以下图所示:
结果说明:默认状况下Action上打了TestFilterAttribute 标签后,虽然在Controller上也打上了此标签,但它只有Action上的标签起做用了。
补充:若是Action没有打上TestFilterAttribute标签,那么Controller上的标签便会被执行。
Index 执行时,Filter的方法只执行了一次,而某些状况下咱们也想让Controller上的FilterAttribute也执行一次TestFilterAttribute,那咱们怎么才能让Controller上的[TestFilter(Message = "controller")]也起做用呢?
答案是:咱们只需在TestFilterAttribute类的定义上打上标记[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]便可【下面类的最上面红色字体部分】,也就是让其成为能够屡次执行的Action。代码以下:
[AttributeUsage(AttributeTargets.All,AllowMultiple = true)] public class TestFilterAttribute:ActionFilterAttribute { public string Message { get; set; } public override void OnActionExecuting(ActionExecutingContext filterContext) { base.OnActionExecuting(filterContext); filterContext.HttpContext.Response.Write("Action执行以前"+Message+"<br />"); } public override void OnActionExecuted(ActionExecutedContext filterContext) { base.OnActionExecuted(filterContext); filterContext.HttpContext.Response.Write("Action执行以后"+Message+"<br />"); } public override void OnResultExecuting(ResultExecutingContext filterContext) { base.OnResultExecuting(filterContext); filterContext.HttpContext.Response.Write("返回Result以前"+Message+"<br />"); } public override void OnResultExecuted(ResultExecutedContext filterContext) { base.OnResultExecuted(filterContext); filterContext.HttpContext.Response.Write("返回Result以后"+Message+"<br />"); } }
浏览效果以下图:
咱们看到的结果是Controller上的ActionFilter先于Action上打的标记执行。一样Result执行executeResult方法以前也是先执行Controller上的Filter标记中的OnResultexecuteing方法。
最后的执行顺序是:Controller上的OnActionExecuting→Action上的OnActionExecuting→Action执行→Action上的OnActionExecuted→Controller上的OnActionExecuted
到此Action就执行完毕了,咱们看到是一个入栈出栈的顺序。后面是Action返回ActionResult后执行了ExecuteResult方法,但在执行以前要执行Filter。具体顺序为:
接上面→Controller的OnResultExecuting方法→Action上的OnResultExecuting→Action返回ActionResult后执行了ExecuteResult方法→Action上的OnResultExecuted执行→Controller上的OnResultExecuted执行→结束。
又接着一个问题也来了,咱们想有些公共的方法须要每一个Action都执行如下,而在全部的Controller打标记是很痛苦的。幸亏Asp。Net MVC3带来了一个美好的东西,全局Filter。而怎么注册全局Filter呢?答案就在Global.asax中。让咱们看如下代码,我是如何将上面咱们定义的TestFilterAttribute 注册到全局Filter中。上代码:
public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute()); //注册全局过滤器 filters.Add(new TestFilterAttribute() { Message="全局"}); }
效果以下图:
咱们看到的结果是全局的Action首先执行,而后才是Controller下的Filter执行,最后才是Action上的标签执行。固然这是在TestFilterAttribute类的定义上打上标记[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]的前提下。否则 若是Action打上了标签跟Controller的相同则它只会执行Action上的Filter。
规定页面的访问形式,如
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Example(){
return View();
}
页面只能以Post形式访问,即表单提交。
规定Action的名称。
应用场景:若是不想用方法名作为Action名,或Action名为关键字的话,如
[ActionName("class")]
public ActionResult Example(){
return View();
}
当前方法仅是普通方法不解析为Action
为Action添加缓存
[OutputCache(Duration = 60, VaryByParam = "*")]
public ActionResult Example()
{
return View();
}
该Action能够接受Html等危险代码(ASP.NET MVC在aspx中设置<%@ Page 的属性没法完成等同任务。)
[ValidateInput(false)]
public ActionResult Example()
{
return View();
}
用于验证服务器篡改。
[ValidateAntiForgeryToken]
public ActionResult Example()
{
return View();
}
通过这一篇文章的介绍咱们大致了解了Filter的使用方法,还了解到全局Filter的用法,尤为是当相同的Filter重复做用到同一个Action上时,若是没有设置可屡次执行的标签那只有Action上的Filter执行,而Controller和全局Filter都被屏蔽掉,可是设置可屡次执行,那首先执行全局Filter其次是Controller再次之就是Action上的Filter了。同时还了解了系统的Filter的用法。
做者:boruipower