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,然后就可以直接重写一下父类的方法如下:
publicvirtualvoid OnActionExecuted(ActionExecutedContext filterContext);//在Action执行之后执行 publicvirtualvoid OnActionExecuting(ActionExecutingContext filterContext); //在Action执行前执行 publicvirtualvoid OnResultExecuted(ResultExecutedContext filterContext);//在Result执行之后 publicvirtualvoid OnResultExecuting(ResultExecutingContext filterContext); //在Result执行之前
然后我们就可以直接在Action、Result执行之前之后分别做一些操作。
第二节:Action Filter实战
光说不练假把式,那现在我们就直接做一个例子来实际演示一下。
首先我们添加一个普通的类,直接上代码吧:
publicclass DemoActionAttributeFilter : ActionFilterAttribute
{
publicstring Message { get; set; } publicoverridevoid OnActionExecuted(ActionExecutedContext filterContext)
{ //在Action执行之后执行 输出到输出流中文字:After Action execute xxx
filterContext.HttpContext.Response.Write(@"<br />After Action execute"+"\t "+ Message);
base.OnActionExecuted(filterContext);
} publicoverridevoid OnActionExecuting(ActionExecutingContext filterContext)
{ //在Action执行前执行
filterContext.HttpContext.Response.Write(@"<br />Before Action execute"+"\t "+ Message);
base.OnActionExecuting(filterContext);
} publicoverridevoid OnResultExecuted(ResultExecutedContext filterContext)
{ //在Result执行之后
filterContext.HttpContext.Response.Write(@"<br />After ViewResult execute"+"\t "+ Message);
base.OnResultExecuted(filterContext);
} publicoverridevoid OnResultExecuting(ResultExecutingContext filterContext)
{ //在Result执行之前
filterContext.HttpContext.Response.Write(@"<br />Before ViewResult execute"+"\t "+ Message);
base.OnResultExecuting(filterContext);
} }
写完这个代码后,我们回到Action上,打上上面的标记如下所示:
[DemoActionAttributeFilter(Message ="action")]
public ActionResult Index()
{ //Action 执行时往输出流写点代码
this.ControllerContext.HttpContext.Response.Write(@"<br />Action execute");
return Content("Result Excut! ");
}
然后执行F5,页面上则会显示为:

最终我们看到了在Action执行之前和之后都执行了我们的重写的DemoActionAttributeFilter方法,Result执行前后也执行了我们的Filter的方法。
总的执行顺序是:
Action执行前:OnActionExecuting方法先执行→Action执行→OnActionExecuted方法执行→OnResultExecuting方法执行→返回的ActionRsult中的executeResult方法执行→OnResultExecuted执行。最终显示的效果就是如上图所示。
感觉很爽吧!呵呵!
如果我们将此标签打到Controller上的话,DemoActionAttributeFilter将作用到Controller下的所有的Action。例如如下代码所示:
[DemoActionAttributeFilter(Message ="controller")]
publicclass HomeController : Controller
{
[DemoActionAttributeFilter(Message ="action")]
public ActionResult Index()
{
this.ControllerContext.HttpContext.Response.Write(@"<br />Action execute");
return Content("<br/>Result Excut! ");
}
}

Index 执行时,Filter的方法只执行了一次,而某些情况下我们也想让Controller上的FilterAttribute也执行一次DemoActionAttributeFilter
那我们怎么才能让Controller上的[DemoActionAttributeFilter(Message = "controller")]也起作用呢?
答案是:我们只需在DemoActionAttributeFilter类的定义上打上标记[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]即可【下面类的最上面红色字体部分】,也就是让其成为可以多次执行的Action。代码如下:
[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
publicclass DemoActionAttributeFilter : ActionFilterAttribute
{
publicstring Message { get; set; } publicoverridevoid OnActionExecuted(ActionExecutedContext filterContext)
{
filterContext.HttpContext.Response.Write(@"<br />After Action execute"+"\t "+ Message);
base.OnActionExecuted(filterContext);
} publicoverridevoid OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.HttpContext.Response.Write(@"<br />Before Action execute"+"\t "+ Message);
base.OnActionExecuting(filterContext);
} publicoverridevoid OnResultExecuted(ResultExecutedContext filterContext)
{
filterContext.HttpContext.Response.Write(@"<br />After ViewResult execute"+"\t "+ Message);
base.OnResultExecuted(filterContext);
} publicoverridevoid OnResultExecuting(ResultExecutingContext filterContext)
{
filterContext.HttpContext.Response.Write(@"<br />Before ViewResult execute"+"\t "+ Message);
base.OnResultExecuting(filterContext);
} }
然后我们执行的效果如图所示:

我们看到的结果是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执行→结束
第三节:Gloable Filter实战
又接着一个问题也来了,我们想有些公共的方法需要每个Action都执行以下,而在所有的Controller打标记是很痛苦的。幸好Asp。Net MVC3带来了一个美好的东西,全局Filter。而怎么注册全局Filter呢?答案就在Global.asax中。让我们看以下代码,我是如何将上面我们定义的DemoActionAttributeFilter 注册到全局Filter中。上代码:
publicclass MvcApplication : System.Web.HttpApplication
{
publicstaticvoid RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
} publicstaticvoid 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
); } protectedvoid 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了。
Asp.Net MVC3 简单教程(三)详解Controller之Filter 【转】的更多相关文章
- Asp.Net MVC3 简单入门第一季(三)详解Controller之Filter
前言 前面两篇写的比较简单,刚开始写这个系列的时候我面向的对象是刚开始接触Asp.Net MVC的朋友,所以写的尽量简单.所以写的没多少技术含量.把这些技术总结出来,然后一简单的方式让更多的人很好的接 ...
- ASP.Net MVC3 图片上传详解(form.js,bootstrap)
图片上传的插件很多,但很多时候还是不能切合我们的需求,我这里给大家分享个我用一个form,file实现上传四张图片的小demo.完全是用jquery前后交互,没有用插件. 最终效果图如下: 玩过花田人 ...
- [MVC.NET] Asp.Net MVC3 简单入门第一季
转自:http://www.cnblogs.com/fly_dragon/archive/2011/10/12/2208042.html 初识Asp.Net MVC2.0 初识Asp.Net MVC2 ...
- GitHub 使用教程图文详解(转)
大纲: 一.前言 二.GitHub简介 三.注册GitHub账号 四.配置GitHub 五.使用GitHub 六.参与GitHub中其它开源项目 七.总结 注,GitHub官网:https://git ...
- GitHub 使用教程图文详解
大纲: 一.前言 二.GitHub简介 三.注册GitHub账号 四.配置GitHub 五.使用GitHub 六.参与GitHub中其它开源项目 七.总结 注,GitHub官网:https://git ...
- asp.net iis URLRewrite 实现方法详解
原文 asp.net iis URLRewrite 实现方法详解 实现非常简单首先你要在你的项目里引用两个dll:actionlessform.dll.urlrewriter.dll,真正实现重写的是 ...
- Asp.net中web.config配置文件详解(一)
本文摘自Asp.net中web.config配置文件详解 web.config是一个XML文件,用来储存Asp.NET Web应用程序的配置信息,包括数据库连接字符.身份安全验证等,可以出现在Asp. ...
- Windows Server 2008 架设 Web 服务器教程(图文详解)
Windows Server 2008 架设 Web 服务器教程(图文详解) 一.安装 IIS 7.0 : 虽然 Windows Server 2008 内置了I IS 7.0,但是默认情况下并没有安 ...
- Windows系统Git安装教程(详解Git安装过程)
Windows系统Git安装教程(详解Git安装过程) 今天更换电脑系统,需要重新安装Git,正好做个记录,希望对第一次使用的博友能有所帮助! 获取Git安装程序 到Git官网下载,网站地址: ...
随机推荐
- 点击图片查看大图(纯js)
$(function(){ $(".pimg").click(function(){ var _this = $(this);//将当前的pimg元素作为_this传入函数 img ...
- Jmeter脚本录制方法(一)分别使用Badboy录制和Jmeter自带的代理服务器录制
Jmeter录制方式分三种,分别是:使用Badboy录制.Jmeter自带的代理服务器录制和手工录制,今天先介绍前两种录制方法. Badboy录制 Badboy是用C++开发的动态应用测试工具, 其拥 ...
- 【Ray Tracing in One Weekend 超详解】 光线追踪1-1
Preface 从这一篇起,我们开始学光线追踪这门牛逼的技术.读了几天,一个字:强! 这一篇我们主要讲述技术入门和一些简单的案例. 我们先学这本: Ready 这本书需要ppmview这个软件帮忙看效 ...
- code vs 1094 FBI树 2004年NOIP全国联赛普及组
题目描述 Description 我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全“1”串称为I串,既含“0”又含“1”的串则称为F串. FBI树是一种二叉树[1],它的结点类型 ...
- div中嵌套img元素,4px空白
写布局的过程中遇到一个问题,在div中嵌套了img元素,没有指定div的高度,嵌套之后div高度始终比img高4个像素,没有设置内外边距,找不到原因. 除非强制div的高度为img的高度,才能使div ...
- 堆排序的C++代码实现
堆排序C++实现 堆排序的具体思路可以查看<算法导论>这本书,一下只提供笔者的C++实现代码,并且将笔者在编写程序的过程当中所遇到的一些细节问题拿出来作一番解释,希望能够对对堆排序有一个透 ...
- 针对MyISAM锁表的解决方案
最近服务器上经常出现mysql进程占CPU100%的情况,使用show processlist命令后,看到出现了很多状态为LOCKED的sql.使用show status like 'table%'检 ...
- 如何快速将Linux文件系统迁移到Azure存储
概述 前一段时间一直在给一个客户将原先搭载在Linux(客户使用的是CentOS 7.0)上的NFS快速迁移到Azure存储上,并且为了保证数据完整性还需要另开一个存储做冷备,架构图如下: 通过Cli ...
- 使用 IntraWeb (2) - Hello IntraWeb
IntraWeb 比我相像中的更贴近 VCL, 传统的非可视组件在这里大都可用(其内部很多复合属性是 TStringList 类型的), 它的诸多可视控件也是从 TControl 继承下来的. 这或许 ...
- spring cloud 学习(5) - config server
分布式环境下的统一配置框架,已经有不少了,比如百度的disconf,阿里的diamand.今天来看下spring cloud对应的解决方案: 如上图,从架构上就可以看出与disconf之类的有很大不同 ...