您的位置:首页 > 编程语言 > ASP

(转)Asp.Net MVC3 简单入门第一季(三)详解Controller之Filter

2011-06-15 15:53 363 查看
转载自:/article/4972877.html

Asp.Net MVC3 简单入门第一季(三)详解ControllerFilter

前言

前面两篇写的比较简单,刚开始写这个系列的时候我面向的对象是刚开始接触AspNet MVC的朋友,所以写的尽量简单。所以写的没多少技术含量。把这些技术总结出来,然后一简单的方式让更多的人很好的接受这是我一直努力的方向。后面会有稍微复杂点的项目!让我们一起期待吧!

此文我将跟大家介绍一下Asp.Net MVC3 Filter的一些用法。你会了解和学习到全局FileterAction Filter等常用用法。

第一节:Filter知识储备

项目大一点总会有相关的AOP面向切面的组件,而MVC(特指:AspNet MVC,以下皆同)项目中呢Action在执行前或者执行后我们想做一些特殊的操作(比如身份验证,日志,异常,行为截取等),而不想让MVC开发人员去关心和写这部分重复的代码,那我们可以通过AOP截取实现,而在MVC项目中我们就可以直接使用它提供的Filter的特性帮我们解决,不用自己实现复杂的AOP了。

AspNet MVC提供了以下几种默认的Filter

Filter
Type


实现接口

执行时间

Default
Implementation


Authorization
filter


IAuthorizationFilter

在所有FilterAction执行之前执行

AuthorizeAttribute

Action filter

IActionFilter

分别在Action执行之前和之后执行。

ActionFilterAttribute

Result filter

IResultFilter

分别在Action Result执行之后和之前

ResultFilterAttribute

Exception filter

IExceptionFilter

只有在filter,

或者 action method, 或者 action result 抛出一个异常时候执行

HandleErrorAttribute

大家注意一点,ActionFilterAttribute默认实现了IActionFilterIResultFilter。而ActionFilterAttribute是一个Abstract的类型,所以不能直接使用,因为它不能实例化,所以我们想使用它必须继承一下它然后才能使用,下图所示的是ActionFilterAttribute的实现:

所以我们在实现了ActionFilterAttribute,然后就可以直接重写一下父类的方法如下:

publicvirtualvoidOnActionExecuted(ActionExecutedContextfilterContext);//Action执行之后执行

publicvirtualvoidOnActionExecuting(ActionExecutingContextfilterContext); //Action执行前执行

publicvirtualvoidOnResultExecuted(ResultExecutedContextfilterContext);//Result执行之后

publicvirtualvoidOnResultExecuting(ResultExecutingContextfilterContext);
//
Result执行之前

然后我们就可以直接在ActionResult执行之前之后分别做一些操作。

第二节:Action Filter实战

光说不练假把式,那现在我们就直接做一个例子来实际演示一下。

首先我们添加一个普通的类,直接上代码吧:

publicclassDemoActionAttributeFilter : ActionFilterAttribute

{

publicstringMessage { get; set;
}


publicoverridevoidOnActionExecuted(ActionExecutedContextfilterContext)

{

//在页面上输出一段文字表示在Action执行完后执行了此段代码

filterContext.HttpContext.Response.Write(@"<br />After Action Excute"+"\t "+Message);

base.OnActionExecuted(filterContext);

}

publicoverridevoidOnActionExecuting(ActionExecutingContextfilterContext)

{

filterContext.HttpContext.Response.Write(@"<br />Before Action Excute"+"\t "+Message);

base.OnActionExecuting(filterContext);

}

publicoverridevoidOnResultExecuted(ResultExecutedContextfilterContext)

{

filterContext.HttpContext.Response.Write(@"<br />After ViewResult Excute"+"\t "+Message);

base.OnResultExecuted(filterContext);

}

publicoverridevoidOnResultExecuting(ResultExecutingContextfilterContext)

{

filterContext.HttpContext.Response.Write(@"<br />Before ViewResult Excute"+"\t "+Message);

base.OnResultExecuting(filterContext);

}

}

写完这个代码后我们回到Action上,打上上面的标记如下所示:

[DemoActionAttributeFilter(Message="action")]

publicActionResultIndex()

{

this.ControllerContext.HttpContext.Response.Write(@"<br />Action Excute");

returnContent("Result Excut! ");

}

然后页面上则会显示为:

最终我们看到了在Action执行之前和之后都执行了我们的重写的DemoActionAttributeFilter方法,Result执行前后也执行了我们的Filter的方法。感觉很爽吧!呵呵!

如果我们将此标签打到Controller上的话,Controller下的所有的Action执行前都会执行一下DemoActionAttributeFilter重写的方法。例如如下代码所示:

[DemoActionAttributeFilter(Message="controller")]

publicclassHomeController : Controller

{

[DemoActionAttributeFilter(Message="action")]

publicActionResultIndex()

{

this.ControllerContext.HttpContext.Response.Write(@"<br />Action Excute");

returnContent("<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)]

publicclassDemoActionAttributeFilter : ActionFilterAttribute

{

publicstringMessage { get; set; }

publicoverridevoidOnActionExecuted(ActionExecutedContextfilterContext)

{

filterContext.HttpContext.Response.Write(@"<br
/>After Action Excute"+"\t
"+Message);

base.OnActionExecuted(filterContext);

}

publicoverridevoidOnActionExecuting(ActionExecutingContextfilterContext)

{

filterContext.HttpContext.Response.Write(@"<br
/>Before Action Excute"+"\t
"+Message);

base.OnActionExecuting(filterContext);

}

publicoverridevoidOnResultExecuted(ResultExecutedContextfilterContext)

{

filterContext.HttpContext.Response.Write(@"<br
/>After ViewResult Excute"+"\t
"+Message);

base.OnResultExecuted(filterContext);

}

publicoverridevoidOnResultExecuting(ResultExecutingContextfilterContext)

{

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打标记是很痛苦的。幸好AspNet MVC3带来了一个美好的东西,全局Filter。而怎么注册全局Filter呢?答案就在Global.asax中。让我们看以下代码,我是如何将上面我们定义的DemoActionAttributeFilter 注册到全局Filter中。上代码:

publicclassMvcApplication : System.Web.HttpApplication

{

publicstaticvoidRegisterGlobalFilters(GlobalFilterCollectionfilters)

{

filters.Add(newHandleErrorAttribute());

}

publicstaticvoidRegisterRoutes(RouteCollectionroutes)

{

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

);

}

protectedvoidApplication_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);

这样我们所有的ActionResult执行前后都会调用我们的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了。

记于:201161423:23:47

谢谢浏览!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: