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,请求服务器(构建请求报文,并且将请求报文发送 ...
随机推荐
- 深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)
作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-language- ...
- 系统中没有邮件客户端设置autoLink=email会挂掉的问题
TextView的autoLink属性为我们提供了很大的便利性,当文本中有网址,邮箱或电话的时候可以让我们方便地执行打电话发邮件等动作,不过也有一些问题,比如说设置autoLink包含email属性, ...
- Oracle ------ SQLDeveloper中SQL语句格式化快捷键
Oracle SQL Developer中SQL语句格式化快捷键: 每次sql复制到SQL Developer面板的时候,格式老不对,而且看起来很不舒服,所有的sql都挤在一行完成. 这时我们可以全选 ...
- Android线程管理之AsyncTask异步任务
前言: 前面几篇文章主要学习了线程以及线程池的创建与使用,今天来学习一下AsyncTask异步任务,学习下AsyncTask到底解决了什么问题?然而它有什么弊端?正所谓知己知彼百战百胜嘛! 线程管理相 ...
- Oracle_数据处理
数据操纵语言 DML(Data Manipulation Language – 数据操纵语言) 可以在下列条件下执行: - 向表中插入数据 - 修改现存数据 - 删除现存数据* 事务是由完成若干项工作 ...
- Hawk 4.3 转换器
转换器是最为常用的一种类型,当然它的使用也是最复杂的. 转换器有三种子类型: A:单文档->单文档:例如仅将某一列的字符提取出来 B:单文档->多文档:典型的如从爬虫转换,每一行url都可 ...
- dagger2系列之生成类实例
上一节的最后,我讲到一次注入生成类实例的生成步骤.先来回顾一下: 1 Module中存在创建方法,则看此创建方法有没有参数 如果有参数,这些参数也是由Component提供的,返回步骤1逐一生成参数 ...
- Java集合专题总结(1):HashMap 和 HashTable 源码学习和面试总结
2017年的秋招彻底结束了,感觉Java上面的最常见的集合相关的问题就是hash--系列和一些常用并发集合和队列,堆等结合算法一起考察,不完全统计,本人经历:先后百度.唯品会.58同城.新浪微博.趣分 ...
- 分布式系统理论进阶 - Paxos变种和优化
引言 <分布式系统理论进阶 - Paxos>中我们了解了Basic Paxos.Multi Paxos的基本原理,但如果想把Paxos应用于工程实践,了解基本原理还不够. 有很多基于Pax ...
- Cesium教程系列汇总
Cesium系列目录: 应用篇 入门 Cesium应用篇:1快速搭建 影像 Cesium应用篇:2影像服务(上) Cesium应用篇:2影像服务(下) 控件 Cesium应用篇:3控件(1)Clock ...