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 大家注意一点,Asp.Net MVC提供的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执行之后执行 输出到输出流中文字:After Action Excute xxx filterContext.HttpContext.Response.Write(@"<br />After Action Excute" + "/t " + Message); base.OnActionExecuted(filterContext); } public override void OnActionExecuting(ActionExecutingContext filterContext) { //在Action执行前执行 filterContext.HttpContext.Response.Write(@"<br />Before Action Excute" + "/t " + Message); base.OnActionExecuting(filterContext); } public override void OnResultExecuted(ResultExecutedContext filterContext) { //在Result执行之后 filterContext.HttpContext.Response.Write(@"<br />After ViewResult Excute" + "/t " + Message); base.OnResultExecuted(filterContext); } public override void OnResultExecuting(ResultExecutingContext filterContext) { //在Result执行之前 filterContext.HttpContext.Response.Write(@"<br />Before ViewResult Excute" + "/t " + Message); base.OnResultExecuting(filterContext); } } 写完这个代码后,我们回到Action上,打上上面的标记如下所示:
[DemoActionAttributeFilter(Message = "action")] public ActionResult Index() { //Action 执行时往输出流写点代码 this.ControllerContext.HttpContext.Response.Write(@"<br />Action Excute"); return Content("Result Excut! "); } 然后执行F5,页面上则会显示为: 最终我们看到了在Action执行之前和之后都执行了我们的重写的DemoActionAttributeFilter方法,Result执行前后也执行了我们的Filter的方法。 总的执行顺序是: Action执行前:OnActionExecuting方法先执行→Action执行→OnActionExecuted方法执行→OnResultExecuting方法执行→返回的ActionRsult中的ExcuteResult方法执行→OnResultExecuted执行。最终显示的效果就是如上图所示。 感觉很爽吧!呵呵! 如果我们将此标签打到Controller上的话,DemoActionAttributeFilter将作用到Controller下的所有的Action。例如如下代码所示: [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! "); } } 那就有个问题了我们再执行显示的页面会有什么情况呢?Controller上的Filter会执行吗?那标签的作用会执行两次吗?下面是最后的执行结果如下图所示: 结果说明:默认情况下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 |