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-6)译 -> TPT继承模型中使用存储过程
10-6. TPT继承模型中使用存储过程 问题 想在一个TPT继承模型中使用存储过程 解决方案 假设已有如Figure 10-6所示模型. 在模型里, Magazine(杂志) and DVD继承于基 ...
- JRebel Windows RegCreateKeyEx(...) returned error code 5.
作为一个JRebel的深度用户,在win10下用JRebel的eclipse插件使用的时候遇到了如下问题: java.util.prefs.WindowsPreferences <init> ...
- exportfs 入门/ 错误
exportfs -uv 不能卸载, exportfs -au 才可以 ================================================================ ...
- Email系列(QQ邮箱 + 含附件的邮箱案例 + 项目实战)
平台之大势何人能挡? 带着你的Net飞奔吧! http://www.cnblogs.com/dunitian/p/4822808.html 邮箱系列:https://github.com/duniti ...
- How to debug .NET Core RC2 app with Visual Studio Code on Windows?
Simone Chiaretta (http://codeclimber.net.nz/archive/2016/05/20/How-to-debug-NET-Core-RC2-app-with-Vi ...
- Handler系列之原理分析
上一节我们讲解了Handler的基本使用方法,也是平时大家用到的最多的使用方式.那么本节让我们来学习一下Handler的工作原理吧!!! 我们知道Android中我们只能在ui线程(主线程)更新ui信 ...
- 重定向Http status code 303 和 302
http 302 http 303 Http 302 302是一个普通的重定向代码.直观的看来是,请求者(浏览器或者模拟http请求)发起一个请求,然后服务端重定向到另一个地址.而事实上,服务端仅仅是 ...
- GridView的使用(高度封装,不怎么灵活,repeat可替代)
GridView的使用 首先,gridview是封装好的,直接在设计界面使用,基本不需要写代码: 一.绑定数据源 GridView最好与LinQDatasourse配合使用,相匹配绑定数据: 二.样式 ...
- [vs2008]Visual Studio 2008 SP1添加或删除功能提示查找SQLSysClrTypes.msi文件
前言 今天接到领导布置的一个任务,是之前同事负责的项目.离职了,现在客户有些地方需要修改,由于我之前参与过,就落在我的头上了. 然后我就把代码弄了过来,打开发现其中需要用到水晶报表.(我觉得不好用,不 ...
- 【无私分享:ASP.NET CORE 项目实战】目录索引
简介 首先,我们的 [无私分享:从入门到精通ASP.NET MVC] 系列已经接近尾声,希望大家在这个过程中学到了一些思路和方法,而不仅仅是源码. 因为是第一次写博客,我感觉还是比较混乱的,其中 ...