(转)Asp.Net MVC3 简单入门第一季(三)详解Controller之Filter
2011-06-15 15:53 音乐让我说 阅读(534) 评论(0) 编辑 收藏 举报转载自:http://www.cnblogs.com/fly_dragon/archive/2011/06/15/2081063.html
Asp.Net MVC3 简单入门第一季(三)详解Controller之Filter
前言
前面两篇写的比较简单,刚开始写这个系列的时候我面向的对象是刚开始接触Asp。Net MVC的朋友,所以写的尽量简单。所以写的没多少技术含量。把这些技术总结出来,然后一简单的方式让更多的人很好的接受这是我一直努力的方向。后面会有稍微复杂点的项目!让我们一起期待吧!
此文我将跟大家介绍一下Asp.Net MVC3 Filter的一些用法。你会了解和学习到全局Fileter,Action Filter等常用用法。
第一节:Filter知识储备
项目大一点总会有相关的AOP面向切面的组件,而MVC(特指:Asp。Net MVC,以下皆同)项目中呢Action在执行前或者执行后我们想做一些特殊的操作(比如身份验证,日志,异常,行为截取等),而不想让MVC开发人员去关心和写这部分重复的代码,那我们可以通过AOP截取实现,而在MVC项目中我们就可以直接使用它提供的Filter的特性帮我们解决,不用自己实现复杂的AOP了。
Asp。Net MVC提供了以下几种默认的Filter:
Filter Type |
实现接口 |
执行时间 |
Default Implementation |
Authorization filter |
IAuthorizationFilter |
在所有Filter和Action执行之前执行 |
AuthorizeAttribute |
Action filter |
IActionFilter |
分别在Action执行之前和之后执行。 |
ActionFilterAttribute |
Result filter |
IResultFilter |
分别在Action Result执行之后和之前 |
ResultFilterAttribute |
Exception filter |
IExceptionFilter |
只有在filter, 或者 action method, 或者 action result 抛出一个异常时候执行
|
HandleErrorAttribute |
大家注意一点,ActionFilterAttribute默认实现了IActionFilter和IResultFilter。而ActionFilterAttribute是一个Abstract的类型,所以不能直接使用,因为它不能实例化,所以我们想使用它必须继承一下它然后才能使用,下图所示的是ActionFilterAttribute的实现:
所以我们在实现了ActionFilterAttribute,然后就可以直接重写一下父类的方法如下:
public virtual void OnActionExecuted(ActionExecutedContext filterContext);//在Action执行之后执行 public virtual void OnActionExecuting(ActionExecutingContext filterContext); //在Action执行前执行 public virtual void OnResultExecuted(ResultExecutedContext filterContext);//在Result执行之后 public virtual void OnResultExecuting(ResultExecutingContext filterContext); //在Result执行之前 |
然后我们就可以直接在Action、Result执行之前之后分别做一些操作。
第二节:Action Filter实战
光说不练假把式,那现在我们就直接做一个例子来实际演示一下。
首先我们添加一个普通的类,直接上代码吧:
public class DemoActionAttributeFilter : ActionFilterAttribute { public string Message { get; set; }
public override void OnActionExecuted(ActionExecutedContext filterContext) { //在页面上输出一段文字表示在Action执行完后执行了此段代码 filterContext.HttpContext.Response.Write(@"<br />After Action Excute" + "\t " + Message); base.OnActionExecuted(filterContext); }
public override void OnActionExecuting(ActionExecutingContext filterContext) { filterContext.HttpContext.Response.Write(@"<br />Before Action Excute" + "\t " + Message); base.OnActionExecuting(filterContext); }
public override void OnResultExecuted(ResultExecutedContext filterContext) { filterContext.HttpContext.Response.Write(@"<br />After ViewResult Excute" + "\t " + Message); base.OnResultExecuted(filterContext); }
public override void OnResultExecuting(ResultExecutingContext filterContext) { filterContext.HttpContext.Response.Write(@"<br />Before ViewResult Excute" + "\t " + Message); base.OnResultExecuting(filterContext); }
}
|
写完这个代码后我们回到Action上,打上上面的标记如下所示:
[DemoActionAttributeFilter(Message = "action")] public ActionResult Index() { this.ControllerContext.HttpContext.Response.Write(@"<br />Action Excute"); return Content("Result Excut! "); }
|
然后页面上则会显示为:
最终我们看到了在Action执行之前和之后都执行了我们的重写的DemoActionAttributeFilter方法,Result执行前后也执行了我们的Filter的方法。感觉很爽吧!呵呵!
如果我们将此标签打到Controller上的话,Controller下的所有的Action执行前都会执行一下DemoActionAttributeFilter重写的方法。例如如下代码所示:
[DemoActionAttributeFilter(Message = "controller")] public class HomeController : Controller { [DemoActionAttributeFilter(Message = "action")] public ActionResult Index() { this.ControllerContext.HttpContext.Response.Write(@"<br />Action Excute"); return Content("<br/>Result Excut! "); } }
|
那就有个问题了我们再执行显示的页面还是一样的,那就是说默认情况下Action上打了DemoActionAttributeFilter 标签后,虽然在Controller上也打上了此标签,但它只有Action上的标签起作用了。
效果图如下图所示:
Index 执行时,Filter的方法只执行了一次,而我们的想法是让Controller上的FilterAttribute也执行一次。DemoActionAttributeFilter
那我们怎么才能让Controller上的[DemoActionAttributeFilter(Message = "controller")]也起作用呢?
答案是:我们只需在DemoActionAttributeFilter类的定义上打上标记[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]即可,也就是让其成为可以多次执行的Action。代码如下:
[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class DemoActionAttributeFilter : ActionFilterAttribute { public string Message { get; set; }
public override void OnActionExecuted(ActionExecutedContext filterContext) { filterContext.HttpContext.Response.Write(@"<br />After Action Excute" + "\t " + Message); base.OnActionExecuted(filterContext); }
public override void OnActionExecuting(ActionExecutingContext filterContext) { filterContext.HttpContext.Response.Write(@"<br />Before Action Excute" + "\t " + Message); base.OnActionExecuting(filterContext); }
public override void OnResultExecuted(ResultExecutedContext filterContext) { filterContext.HttpContext.Response.Write(@"<br />After ViewResult Excute" + "\t " + Message); base.OnResultExecuted(filterContext); }
public override void OnResultExecuting(ResultExecutingContext filterContext) { filterContext.HttpContext.Response.Write(@"<br />Before ViewResult Excute" + "\t " + Message); base.OnResultExecuting(filterContext); }
}
|
然后我们执行的效果如图所示:
我们看到的结果是Controller上的ActionFilter先于Action上打的标记执行。同样Result执行ExcuteResult方法之前也是先执行Controller上的Filter标记中的OnResultExcuteing方法。
第三节:Gloable Filter实战
又接着一个问题也来了,我们想有些公共的方法需要每个Action都执行以下,而在所有的Controller打标记是很痛苦的。幸好Asp。Net MVC3带来了一个美好的东西,全局Filter。而怎么注册全局Filter呢?答案就在Global.asax中。让我们看以下代码,我是如何将上面我们定义的DemoActionAttributeFilter 注册到全局Filter中。上代码:
public class MvcApplication : System.Web.HttpApplication { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute()); }
public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults );
}
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); GlobalFilters.Filters.Add(new DemoActionAttributeFilter() { Message = "Gloable" }); RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes); } }
|
跟普通的MVC2.0中的Global.asax的区别就是红色部分的代码,我们看到代码中我将自己定义的DemoActionAttributeFilter的实例加入到GlobalFilters.Filters集合中,然后下面一句就是注册全局Filter:RegisterGlobalFilters(GlobalFilters.Filters);
这样我们所有的Action和Result执行前后都会调用我们的DemoActionAttributeFilter的重写的方法。
再次运行我们的demo看到的结果是:
我们看到的结果是全局的Action首先执行,然后才是Controller下的Filter执行,最后才是Action上的标签执行。当然这是在DemoActionAttributeFilter类的定义上打上标记[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]的前提下。不然 如果Action打上了标签跟Controller的相同则它只会执行Action上的Filter。
总结:经过这一篇文章的介绍我们大体了解了Filter的使用方法,还了解到全局Filter的用法,尤其是当相同的Filter重复作用到同一个Action上时,如果没有设置可多次执行的标签那只有Action上的Filter执行,而Controller和全局Filter都被屏蔽掉,但是设置可多次执行,那首先执行全局Filter其次是Controller再次之就是Action上的Filter了。
记于:2011年6月14日23:23:47
谢谢浏览!
作者:音乐让我说(音乐让我说 - 博客园)
出处:http://music.cnblogs.com/
文章版权归本人所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。