阅读目录:

  • 1.开篇介绍

  • 2.ASP.NETMVC Controller 控制器的入口(Controller的执行流程)

  • 3.ASP.NETMVC Controller 控制器的入口(Controller的继承体系)

  • 4.ASP.NETMVC IController Factory 控制器工厂(Controller的创建)

1】开篇介绍

经过前一篇文章.NET/ASP.NET Routing路由(深入解析路由系统架构原理) 的讲解,我们对ASP.NETRouting路由系统的整个运行机制有了一个基本的了解;当我们能清楚的知道Url是如何被解析成RouteData对象时,下面就是这些路由数据是如何被后面的应用框架所使用的,而通往应用框架的入口是MvcRouteHandler对象;

这篇文章将继续讲解通过路由后的ASP.NETMVC Controller控制器是如何被加载、激活并且执行的;跟控制器相关的一套对象模型是被MvcHandler对象作为源头调用起来的,也就是说,当我们穿过UrlRoutingModule对象后,并且成功的获取到应用框架配置的路由数据后,下面将进入IHttpHandler接口,而这个接口真是我们初始化RouteData对象时设定的应用框架入口,ASP.NETMVC所使用的是MvcHandler对象;

MvcRouteHandler对象是UrlRoutingModuleMvcHandler对象的连接器,只有MvcRouteHandler对象能成功执行后,方能进入到MvcHandler对象中,后续的一切运转才能顺利执行;

2】ASP.NETMVC Controller 控制器的入口(Controller的执行流程)

在系统刚启动的时候,也就是在Global.asax.cs文件里面我们配置了Http客户端请求服务器的Url模板;在路由解析模块(UrlRoutingModule)里面,它将通过字符串级别的操作,解析出我们Url模板中的{Controller}/{Action}等的占位符变量;所以这个时候Controller的概念对我们来说还只是一个字符串而已,而到了目前的这个Controller控制器解析的位置其实已经和路由基本没关系了,因为我们穿过了路由模块到达了Controller解析的环节;Controller解析已经属于ASP.NETMVC应用框架的范围,我们可以简单的将路由解析(UrlRoutingModule)的过程视为将请求的Url(含有数据的Url)与我们配置的Url模板进行模式匹配的过程,得出匹配后的Url数据(RouteData),然后将Url数据并且连同当前请求上下文一起封装成RequestContext对象(RouteData、HttpContextBase)传入到Controller解析的环节,也就是MvcHandler中,作为MvcHandler构造函数的参数;

当MvcHandler接管控制权之后它需要准备好对Controller的解析和执行,但是Controller并发一个简单的对象,它有一个复杂的继承体系和使用方式,原因在于它需要协调多方面的工作所以变的有很复杂;

根据MVC的架构模式理论便知道Controller是协调Model与View的中间纽带,它既要管理好Model的执行,也要管理好View的呈现;而原本MVC的架构模式提出的背景是在WinFrom的情况下,也就是传统C/S结构的系统;WinFrom结构的系统有一个好处就是它的执行很方便,从View的展现收集数据到Controller的调度执行Model会容易完成,但是ASP.NETMVC是建立在ASP.NET WEB背景之下的MVC模式框架,所以这个时候对Controller的激活会变的相当麻烦,因为在传输过程中Controller已经是字符串形式,如果是在C/S结构中那么Controller对于每次处理一样的View不会每次都进行激活;既然每次都需要激活就需要进行缓存策略,缓存策略只是Controller中的一个关键点,需要明白的是Controller的确需要做很多事情;

图1:

根据上图的执行顺序,能看出Controller控制器扮演着一个很重要的角色,所有的执行、返回值、视图呈现均需要通过它来管理调度;当然本章的重点是搞清楚此图中的第一环节,Controller是如何被加载激活的,这里面将涉及到众多的辅助对象模型,比如:ControllerFactory控制器工厂,而控制器工厂又将借助ControllerTypeCache来缓存Controller对象,而ConrollerTypeCache又将借助TypeCacheSerializer来对Controller缓存文件的序列化;

3.ASP.NETMVC Controller 控制器的入口(Controller的继承体系)

Controller控制器既然扮演着重要的角色,那么它就不会是一个简单的对象结构,它有着一个复杂的继承体系和对象模型支撑它来完成这些艰巨的任务;Controller要想能够运行起来,就需要搞清楚它有哪些执行入口,而需要知道它有哪些执行入口我们就需要搞清楚它的继承体系;入口的最高层抽象在哪一层,这样我们才能举一反三的扩展Controller的众多重要的功能;

首先我们了解到Controller的顶层抽象是IController接口,然后接着是ControllerBase抽象类实现了这个接口,而作为顶层抽象的实现ControllerBase完成了从IController接口继承下来的方法;

1
2
3
public interface IController {
    void Execute(RequestContext requestContext);
}

通过该代码段可以看出,Controller的执行需要一个RequestContext对象,而这个对象真是UrlRoutingModule环节所完成的结果,RequestContext对象内部封装了在Request阶段所获得的请求数据,里面包括了跟Http相关的请求上下文(HttpContextBase),最重要的是路由数据对象(RouteData);而控制器的执行必须需要RouteData中的有关Controller数据对象,也就是从请求Url中通过模式匹配出来的{Controller}部分的字符串;

ControllerBase定义了Controller使用到的部分公共属性,比如:用来保存临时数据的TempData,用来返回到View中的Model数据对象ViewBag、ViewData;并且初始化了ControllerContext对象,用来作为后续Controller使用的数据容器和操作上下文;

1
2
3
protected virtual void Initialize(RequestContext requestContext) {
    ControllerContext = new ControllerContext(requestContext, this);
}

在ControllerBase中将对IController.Execute(RequestContext requestContext)方法调用转到了protected abstract void ExecuteCore()方法中;这是一个典型的模板方法模式,下面的继承类Controller,只需要接着protected abstract void ExecuteCore()方法就能和ControllerBase衔接上;

1
public abstract class Controller : ControllerBase

Controller类继承自ControllerBase,而Controller的任务只需要完成ExecuteCore()方法;

1
2
3
4
5
6
7
8
9
10
11
12
protected override void ExecuteCore() {
           PossiblyLoadTempData();
           try {
              string actionName = RouteData.GetRequiredString("action");
               if (!ActionInvoker.InvokeAction(ControllerContext, actionName)) {
                   HandleUnknownAction(actionName);
               }
           }
           finally {
               PossiblySaveTempData();
           }
       }

Controller.ExecuteCore()的代码将从RouteData中获取执行action的名称,然后通过一个ActionInvoke的组件进行Action的调用,当Action被执行的时候将进入到我们继承的Controller,如:HomeController:Controller中,在我们自定的Controller中的方法都将被视为Action的匹配目标之一;

图2:

根据上图的指示,ControllerBase首先是实现IController接口,完成了对Execute(RequestContext requestContext)方法的实现,然后Controller继承ControllerBase类,重写了模板方法ExecuteCore()方法,然后我们自定义的HomeController其实是Action的容器,当Controller的ExecuteCore()方法执行时将通过ActionInvoke类进行对HomeController中的方法调用;

4.ASP.NETMVC IController Factory 控制器工厂(Controller的创建)

当清楚了Controller的继承体系之后,下面回到MvcHandler调用的环节;MvcHandler继承自IHttpHandler接口 ,表示它将是ASP.NET真正执行请求处理的地方;在MvcHandler处理请求的方法中ProcessRequest(HttpContextBase httpContext),将通过IControllerFactory接口创建IController接口;

IControllerFactory接口是控制器工厂接口,专门用来实现创建IController对象工厂类,在ASP.NETMVC内部有一个实现了IControllerFactory接口的默认工厂类DefaultControllerFactory,ASP.NETMVC内部是用这个类来创建IController对象的;

1
factory = ControllerBuilder.GetControllerFactory();

获取IDefaultControllerFactory接口需要通过ControllerBuilder对象,ControllerBuilder类是专门用来管理IControllerFactory对象的,同时ControllerBuilder也是应用编程接口,让自定义IControllerFactory对象成为可能;

创建IController需要我们传入RequestContext对象和ControllerName控制器名称;

1
2
3
4
// Get the controller type
string controllerName = RequestContext.RouteData.GetRequiredString("controller");
factory = ControllerBuilder.GetControllerFactory();
controller = factory.CreateController(RequestContext, controllerName);

从RequestContext.RouteData中获取到当前请求的conroller名称,然后用来作为factory.CreateController的参数;

图3:

MvcHandler通过ControllerBuilder对象的静态属性Current获取到ControllerBuilder对象实例,显然ControllerBuilder是一个单例模式的对象;然后通过ControllerBuilder对象获取到DefaultControllerFactory默认IControllerFactory工厂对象,接着利用DefaultControllerFactory创建出IController对象;

作者:王清培

出处:http://wangqingpei557.blog.51cto.com/

本文版权归作者和51CTO共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

NET/ASP.NET MVC Controller 控制器(一:深入解析控制器运行原理)的更多相关文章

  1. .NET/ASP.NET MVC Controller 控制器(IController控制器的创建过程)

    阅读目录: 1.开篇介绍 2.ASP.NETMVC IControllerFactory 控制器工厂接口 3.ASP.NETMVC DefaultControllerFactory 默认控制器工厂 4 ...

  2. 三、ASP.NET MVC Controller 控制器(二:IController控制器的创建过程)

    阅读目录: 1.开篇介绍 2.ASP.NETMVC IControllerFactory 控制器工厂接口 3.ASP.NETMVC DefaultControllerFactory 默认控制器工厂 4 ...

  3. ASP.NET MVC 5 学习教程:通过控制器访问模型的数据

    原文 ASP.NET MVC 5 学习教程:通过控制器访问模型的数据 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 创建连 ...

  4. ASP.NET MVC 5 学习教程:添加控制器

    原文 ASP.NET MVC 5 学习教程:添加控制器 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 创建连接字符串 通过 ...

  5. 【译】ASP.NET MVC 5 教程 - 6:通过控制器访问模型的数据

    原文:[译]ASP.NET MVC 5 教程 - 6:通过控制器访问模型的数据 在本节中,你将新建一个MoviesController 类,并编写获取电影数据的代码,使用视图模板将数据展示在浏览器中. ...

  6. 【译】ASP.NET MVC 5 教程 - 2:添加控制器

    原文:[译]ASP.NET MVC 5 教程 - 2:添加控制器 MVC 表示 模型-视图-控制器.MVC 是一种用于开发应用程序的模式,具备良好架构,可测试和易于维护.基于 MVC 应用程序中包含: ...

  7. .NET/ASP.NET MVC Controller 控制器(深入解析控制器运行原理)

    阅读目录: 1.开篇介绍 2.ASP.NETMVC Controller 控制器的入口(Controller的执行流程) 3.ASP.NETMVC Controller 控制器的入口(Controll ...

  8. 二、ASP.NET MVC Controller 控制器(一:深入解析控制器运行原理)

    阅读目录: 1.开篇介绍 2.ASP.NETMVC Controller 控制器的入口(Controller的执行流程) 3.ASP.NETMVC Controller 控制器的入口(Controll ...

  9. Asp.Net MVC学习总结(二)——控制器与动作(Controller And Action)

    一.理解控制器 1.1.什么是控制器 控制器是包含必要的处理请求的.NET类,控制器的角色封装了应用程序逻辑,控制器主要是负责处理请求,实行对模型的操作,选择视图呈现给用户. 简单理解:实现了ICon ...

随机推荐

  1. sublime text3常用快捷键

    Ctrl+L 选择整行(按住-继续选择下行) Ctrl+KK 从光标处删除至行尾 Ctrl+Shift+K 删除整行 Ctrl+Shift+D 复制光标所在整行,插入在该行之前 Ctrl+J 合并行( ...

  2. maven中package和install命令的区别

    mvn package 编译并打包工程,根据pom文件中packaging是jar还是war进行打包,会在项目的target目录下生成一个jar/war包. mvn install 打包并安装到mav ...

  3. Mayor's posters(线段树+离散化+区间染色)

    题目链接:http://poj.org/problem?id=2528 题目: 题意:将n个区间进行染色(对于同一个区间,后一次染色会覆盖上一次的染色),问最后可见的颜色有多少种. 思路:由于区间长度 ...

  4. Js如何动态声明变量名

    做个笔记~ var a = 5; for (var i = 1; i <= a; i++) { eval("var a" + i + "=" + i); ...

  5. bzoj 1968 数学

    在1-n所有数中,i一共可以成为n/i个数的约数,也即所有的约数中有n/i个i,所以扫一遍累加答案就好了. /********************************************* ...

  6. 网页实现插入图片—css与html的区别

    Q1.二者有何区别?A1.写在css里面的图片是以背景图形式存在的,而写在html里的是以<img>标签形式存在的,在网页加载的过程中,以css背景图存在的图片会等到结构加载完成(网页的内 ...

  7. hdu 1166敌兵布阵(线段树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166 敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    M ...

  8. 【tomcat】手动部署动态JavaWeb项目到tomcat

    1.通过修改server.xml进行配置 1.查看项目的目录结构: tomcat运行时加载WebConmtent目录

  9. 用python玩微信(聊天机器人,好友信息统计)

    1.用 Python 实现微信好友性别及位置信息统计 这里使用的python3+wxpy库+Anaconda(Spyder)开发.如果你想对wxpy有更深的了解请查看:wxpy: 用 Python 玩 ...

  10. Python3 文件基本操作

    Python文件的打开模式有: r,只读模式(默认).w,只写模式.[不可读:不存在则创建:存在则删除内容:]a,追加模式.[可读: 不存在则创建:存在则只追加内容:]"+" 表示 ...