asp.net mvc 之旅 —— 第六站 ActionFilter的应用及源码分析
这篇文章我们开始看一下ActionFilter,从名字上其实就大概知道ActionFilter就是Action上的Filter,对吧,那么Action上的Filter大概有几个呢???
这个问题其实还是蛮简单的,因为我们听说Mvc本身就是一个扩展性极强的框架,自然就是层层有拦截,层层有过滤,对吧,比如我们看到的如下Controller类。
public abstract class Controller : ControllerBase, IActionFilter, IAuthenticationFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter, IAsyncController, IController, IAsyncManagerContainer
{
}
从这个父类的Controller中,我们就可以看到有5个Filter,如:IActionFilter,IAuthenticationFilter,IAuthorizationFilter,IExceptionFilter,IResultFilter,
对吧,首先我们还是从第一个ActionFilter说起。
一:IActionFilter解析
现在我们知道IActionFilter是一个接口,接下来感兴趣的就是这个ActionFilter里面到底是什么,比如我下面截图的这样。
//
// 摘要:
// Defines the methods that are used in an action filter.
public interface IActionFilter
{
//
// 摘要:
// Called after the action method executes.
//
// 参数:
// filterContext:
// The filter context.
void OnActionExecuted(ActionExecutedContext filterContext);
//
// 摘要:
// Called before an action method executes.
//
// 参数:
// filterContext:
// The filter context.
void OnActionExecuting(ActionExecutingContext filterContext);
}
从上面这段代码中,我们可以看到其实这个接口里面只有两个方法,一个是OnActionExecuting,一个是OnActionExecuted,看这名字你应该就明白
其实就是在Action的前后分别执行,对吧,那这样的话,聪明的你就想到了应用场景,记录日志,获取action的访问量,以方便后续收费~~~ 接下来我
们来看看怎么来实现这两个方法。
1. 用override的方式实现ActionFilter
现在大家都知道Controller类已经实现了这个接口,那我们自己的XXXController刚好又继承了这个父Controller,所以面对这种情况,我们可以用
override来实现,比如下面我实现的这样。
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
} protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.HttpContext.Response.Write("hello"); base.OnActionExecuting(filterContext);
} protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
filterContext.HttpContext.Response.Write("world"); base.OnActionExecuted(filterContext);
}
}
就这样我们就轻松加愉快的实现了,是不是很简单,但是仔细一想,这样的方法还是有一点限制的,也就是说我们override的依赖性太强了,比如说只有
class extends IActionFilter才可以,接下来我们再看有没有更灵活的方法来实现。
2. 自定义class extends IActionFilter
要想做到高度的灵活性,我们必须将这个实现类做成一个“原子单位”,有了这个原子单位,我们就可以很方便的将这个不可拆解的原子性应用到各个地方
去,对吧,这个原子在C#中可以用Attribute来实现,比如下面这样:
public class MyActionFilterAttribute : Attribute, IActionFilter
{
public void OnActionExecuted(ActionExecutedContext filterContext)
{
filterContext.HttpContext.Response.Write("hello");
} public void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.HttpContext.Response.Write("world");
}
}
ok,现在我们已经得到了一个原子性质的MyActionFilterAttribute特性,接下来我们可以将这个MyActionFilterAttribute应用到任何地方,如下图:
public class HomeController : Controller
{
[MyActionFilter]
public ActionResult Index()
{
return View();
}
}
3. ActionFilterAttribute
除了我们实现以下Attribute特性和IActionFilter接口,我们还可以继承一个mvc框架提供给我们的ActionFilterAttribute特性,迫不及待的看一下吧~
//
// 摘要:
// Represents the base class for filter attributes.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IResultFilter
{
//
// 摘要:
// Initializes a new instance of the System.Web.Mvc.ActionFilterAttribute class.
protected ActionFilterAttribute(); //
// 摘要:
// Called by the ASP.NET MVC framework after the action method executes.
//
// 参数:
// filterContext:
// The filter context.
public virtual void OnActionExecuted(ActionExecutedContext filterContext);
//
// 摘要:
// Called by the ASP.NET MVC framework before the action method executes.
//
// 参数:
// filterContext:
// The filter context.
public virtual void OnActionExecuting(ActionExecutingContext filterContext);
//
// 摘要:
// Called by the ASP.NET MVC framework after the action result executes.
//
// 参数:
// filterContext:
// The filter context.
public virtual void OnResultExecuted(ResultExecutedContext filterContext);
//
// 摘要:
// Called by the ASP.NET MVC framework before the action result executes.
//
// 参数:
// filterContext:
// The filter context.
public virtual void OnResultExecuting(ResultExecutingContext filterContext);
}
从这个Attribute中可以看到,它整合了IActionFilter, IResultFilter,自然就有了这两个接口的方法,好了,不多说,我们来实现一下这个抽象类吧。
namespace WebApplication2.Controllers
{
public class HomeController : Controller
{
[MyActionFilter]
public ActionResult Index()
{
return View();
}
} public class MyActionFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
} public override void OnActionExecuted(ActionExecutedContext filterContext)
{
base.OnActionExecuted(filterContext);
}
}
}
二:源码分析
最好的源码分析方法,肯定是希望你下载一个reflector插件,这样我们就可以获取到运行时的可调试代码以及可以看到的调用堆栈,尤其是”调用堆
栈“,对你来说非常的重要。
1. 首先我们下一个断点在 OnActionExecuting方法里面,如下图:
2. 通过调用堆栈回退到上一个堆栈,如图:
这个方法其实非常的有意思,从方法名称中可以看到,其实它是一个递归的模式,也就是”OnActionExecuting" =>"进栈执行BeginInvokeActionMethod”
=>"退栈执行OnActionExecuted“方法,因为有一个非常好看的statement,比如:
Func<ActionExecutedContext> continuation = this.InvokeActionMethodFilterAsynchronouslyRecursive(num);
好了,更多的细节等待你去考究,希望本篇文章对您有帮助~~~
asp.net mvc 之旅 —— 第六站 ActionFilter的应用及源码分析的更多相关文章
- asp.net mvc 之旅—— 第三站 路由模板中强大的自定义IRouteConstraint约束
我们在写mvc的时候,经常会配置各种url模板,比如controller,action,id 组合模式,其实呢,我们还可以对这三个参数进行单独的配置,采用的方式自然 就是MapRoute中的const ...
- asp.net mvc 之旅 —— 第五站 从源码中分析asp.net mvc 中的TempData
在mvc的controller中,我们知道有很多的临时变量存放数据,比如说viewData,viewBag,还有一个比较特殊的tempData,关于前两个或许大家都明白, 基本上是一个东西,就是各自的 ...
- asp.net mvc 之旅—— 第四站 学会用Reflector调试我们的MVC框架代码
我们知道,现在能调试.net程序通常有两个,第一个是ILSpy,还是一个是Reflector,这两个小反编译软件算是我们研究底层代码中所拥有的一把 锋利小尖刀~~~,比如你看到的ILSpy这样的界面图 ...
- Cocos2d-X3.0 刨根问底(六)----- 调度器Scheduler类源码分析
上一章,我们分析Node类的源码,在Node类里面耦合了一个 Scheduler 类的对象,这章我们就来剖析Cocos2d-x的调度器 Scheduler 类的源码,从源码中去了解它的实现与应用方法. ...
- 第六篇:Spark SQL Catalyst源码分析之Physical Plan
/** Spark SQL源码分析系列文章*/ 前面几篇文章主要介绍的是spark sql包里的的spark sql执行流程,以及Catalyst包内的SqlParser,Analyzer和Optim ...
- concurrent(六)同步辅助器CyclicBarrier & 源码分析
参考文档:Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例:https://www.cnblogs.com/skywang12345/p/3533995.html简介Cy ...
- Asp.net mvc 知多少(六)
本系列主要翻译自<ASP.NET MVC Interview Questions and Answers >- By Shailendra Chauhan,想看英文原版的可访问http:/ ...
- ASP.NET MVC 4源码分析之如何定位控制器
利用少有的空余时间,详细的浏览了下ASP.NET MVC 4的源代码.照着之前的步伐继续前进(虽然博客园已经存在很多大牛对MVC源码分析的博客,但是从个人出发,还是希望自己能够摸索出这些).首先有一个 ...
- ASP.NET WebForm / MVC 源码分析
浏览器 Url:https//localhost:6565/Home/Index ,https//localhost:6565/WebForm1.aspx,请求服务器(构建请求报文,并且将请求报文发送 ...
随机推荐
- Entity Framework 6 Recipes 2nd Edition(10-1)译->非Code Frist方式返回一个实体集合
存储过程 存储过程一直存在于任何一种关系型数据库中,如微软的SQL Server.存储过程是包含在数据库中的一些代码,通常为数据执行一些操作,它能为数据密集型计算提高性能,也能执行一些为业务逻辑. 当 ...
- 【PRINCE2是什么】PRINCE2认证之七大原则(5)
我们先来回顾一下,PRINCE2七大原则分别是持续的业务验证,经验学习,角色与责任,按阶段管理,例外管理,关注产品,剪裁. 第五个原则:例外管理. PRINCE2对每个项目目标都定义了容许偏差来建立授 ...
- Python学习--03变量类型
变量赋值 Python中的变量不需要声明,变量的赋值操作既是变量声明和定义的过程. 每个变量在内存中创建,都包括变量的标识,名称和数据这些信息. 每个变量在使用前都必须赋值,变量赋值以后该变量才会被创 ...
- PHP日志压缩下载
主要实现了在后台查看日志列表及打包下载功能. 由于用到了PHP压缩功能,特此记录下. 压缩下载类: Hzip.php <?php /** * Created by PhpStorm. * @au ...
- [转载]Google Guava官方教程(中文版)
原文链接 译文链接 译者: 沈义扬,罗立树,何一昕,武祖 校对:方腾飞 引言 Guava工程包含了若干被Google的 Java项目广泛依赖 的核心库,例如:集合 [collections] ...
- ios 音视频实现边播边缓存的思路和解决方案 (转)
本片为转载内容,主要是以后自己看起来方便一些 原文地址:iOS音视频实现边下载边播放 其实音视频本地缓存的思想都差不多,都需要一个中间对象来连接播放器和服务器. 近段时间制作视频播放社区的功能,期间查 ...
- 如何修复VUM在客户端启用之后报数据库连接失败的问题
在上一篇随笔中介绍了关于重新注册VMware Update Manager(VUM)至vCenter Server中的方法,最近有朋友反应,原本切换过去好好的更新服务为什么某次使用一下就不灵了? 当时 ...
- MFC&Halcon之实时视频监控
上一篇实现了在MFC的窗体内显示图片,本篇介绍如何在MFC窗体内实时显示摄像头的影像. 要实现的功能是点击一个“开始”按钮,可以显示影像,再点击“停止”按钮,可以停止显示. 因为实时显示影像需要在一个 ...
- jQuery.ajax 根据不同的Content-Type做出不同的响应
使用H5+ASP.NET General Handler开发项目,使用ajax进行前后端的通讯.有一个场景需求是根据服务器返回的不同数据类型,前端进行不同的响应,这里记录下如何使用$.ajax实现该需 ...
- 完美解决,浏览器下拉显示网址问题 | 完美解决,使用原生 scroll 写下拉刷新
在 web 开发过程中我们经常遇到,不想让用户下拉看到我的地址,也有时候在 div 中没有惯性滚动,就此也出了 iScroll 这种关于滚动条的框架,但是就为了一个体验去使用一个框架好像又不值得,今天 ...