ASP.NET没有魔法——ASP.NET MVC Controller的实例化与执行
上一章节中对路由的注册和匹配过程进行了介绍,知道了MVC的Http请求最终是交由MvcHandler处理的,而其处理过程就是对Controller的创建、执行和释放。
本章将从以下几点进一步对上面提到的三个过程进行介绍:
● MvcHandler概述
● ControllerBuilder&ControllerFactory
● DefaultControllerFactory
● Controller&ControllerBase
● Controller的执行
MvcHandler概述
MvcHandler是MVC的核心组件,用于接收并处理来自客户的MVC请求,以下是MvcHandler类型的定义:

MvcHandler实现了IHttpHandler和异步的IHttpAsyncHandler接口,这两个接口是用于处理Http请求的接口,其实这里所谓的“处理”就是根据用户请求的信息来生成一个响应信息返回到客户端。所以Mvc中也一样,通过Http请求的Head、Body等信息从中抓取需要的数据,然后将其传入Controller的Action中执行业务逻辑后,渲染一个Html模板返回至客户端显示。
它的构造需要一个RequestContext对象。而RequestContext其实是HttpContextBase(包含了HTTP请求的所有信息)和RouteData的封装,这个对象是在UrlRoutingModule中创建的,然后通过MvcRouteHandler传到了MvcHandler中。
以下是MvcHandler的处理概况图:


ControllerBuilder&ControllerFactory
MvcHandler执行的一个步骤就是初始化,其中最重要的就是创建Controller,而Controller的创建离不开ControllerBuilder和ControllerFactory,那么它们到底起到什么作用?
1. ControllerBuilder:用于获取和设置ControllerFactory,在没有设置过ControllerFactory的情况下默认获得DefaultControllerFactory。
以下是ControllerBuilder的定义:

2. ControllerFactory:它其实是一个IControllerFactory接口,专门用于创建和销毁Controller。MVC的默认实现是DefaultControllerFactory。

综上所述,ControllerBuilder用于创建ControllerFactory,而ControllerFactory用于创建Controller,而ControllerFactory的默认实现是DefaultControllerFactory。
DefaultControllerFactory
以下是DefaultControllerFactory的定义:

它除了实现IControllerFactory的方法外还有两个名为GetControllerInstance、GetControllerType的受保护的虚方法,另外构造方法有一个类型为IControllerActivator的参数。前者很容易理解,在.Net中可以通过一个类型来创建一个实例,而可以通过类型名称在程序集中找到对应的类型。所以可以想到的是两个方法分别就是根据Controller的名称获取类型然后在通过类型创建实例的方法。而后者从名称看来是Controller的激活器,那它的作用是什么呢?是用来创建Controller实例的吗?
以下是CreateController的代码,从代码中也证实了上面的猜测,Controller的创建是先根据Controller名称查找类型,然后通过类型创建Controller实例。

1. Controller类型的查找:
1). 命名空间的处理:路由中的命名空间、ControllerBuilder中的命名空间、无命名空间;三种命名空间从前到后依次以其值来作为命名空间匹配,直到找到对应Controller的类型。换句话说如果路由对象和Controller Builder都设置了命名空间,那么先根据路由对象的去查找,如果找不到再使用ControllerBuilder设置的命名空间,如果仍然没有就不使用命名空间来进行匹配。
2). Controller类型缓存数据处理:为了提高MVC的性能,在通过缓存的形式在第一次查找Controller类型的时候遍历所有依赖程序集中的IController类型生成一个名称为“MVC-ControllerTypeCache.xml”缓存文件(由ControllerTypeCache类型完成),以下是缓存文件格式:

注:该缓存路径一般在systemroot\Microsoft .NET\Framework\versionNumber\Temporary ASP.NET Files\{app name}\..\..\UserCache或systemroot\Microsoft .NET\Framework\versionNumber\Temporary ASP.NET Files\root\..\..\UserCache目录下,但是可能由于Web宿主不同或环境配置不同而不同,但是可以在代码中通过HttpRuntime.CodegenDir属性找到。另外还有一个缓存文件是对Area注册的缓存,名称为MVC-AreaRegistrationTypeCache.xml。
3). 类型的匹配:Controller的类型匹配相对简单,它使用{NameSpace}.{ControllerName}的形式在上面文件的数据结构中匹配。
2. Controller的创建:
1). 判断Controller类型是否是继承于IController。
2). 通过ControllerActivator创建Controller实例。
3. 关于ControllerActivator:用于Controller的创建,在MVC中有一个DefaultControllerActivator存在于DefaultControllerFactory中,它用于通过.Net中的Activator对象或依赖解析器创建Controller实例。

Controller&ControllerBase
在开发中MVC控制器的时候,一般以Controller类型作为基类,通过继承的方式来完成。这样可以轻松的获得Controller基类提供的功能。而Controller其实是继承至ControllerBase抽象类,ControllerBase中提供了MVC中最核心的Execute方法和ExecuteCore抽象方法以及必要的一些属性如TempDataDictionary以及ViewDataDictionary等,使用典型的模板模式规定了Controller类型的框架。
1. ControllerBase:定义了Controller的核心框架

2. Controller:实现了ASP.NET MVC中控制器的执行逻辑,以及附加功能,如验证、异常处理、事件处理(Action执行事件、验证事件等)、跳转、多种返回类型(包括但不限于MVC页面、Json数据、文件、普通内容)等。
注:由于Controller定义代码太多,所以不在放出,大家可以在VS中查看。
Controller的执行
上面提到过ControllerBase是整个Controller类结构的模板,所以在ASP.NET MVC调用Controller执行时实际上是调用的ControllerBase类型的Execute方法,而该方法内部实际上调用的是子类的ExecuteCore方法,以下是Controller类型的ExecuteCore:

从代码可以看出Controller的执行“很”简单,只有四步:加载临时数据、获取Action、执行Action、保存临时数据。
注:本章不再对Action的执行进行介绍,因为Action的执行包含了很多内容,比如过滤器的执行、模型的绑定等,所以这些内容会在后续讲解。
小结
本章以MvcHandler的执行为入口,以MVC控制器的创建、执行为流程,介绍了其相关的重要对象和执行逻辑。更多内容请关注后续文章。
本文链接:http://www.cnblogs.com/selimsong/p/7677108.html
ASP.NET没有魔法——ASP.NET MVC Controller的实例化与执行的更多相关文章
- ASP.NET没有魔法——ASP.NET MVC 过滤器(Filter)
上一篇文章介绍了使用Authorize特性实现了ASP.NET MVC中针对Controller或者Action的授权功能,实际上这个特性是MVC功能的一部分,被称为过滤器(Filter),它是一种面 ...
- ASP.NET没有魔法——ASP.NET MVC 模型绑定解析(下篇)
上一篇<ASP.NET没有魔法——ASP.NET MVC 模型绑定解析(上篇)>文章介绍了ASP.NET MVC模型绑定的相关组件和概念,本章将介绍Controller在执行时是如何通过这 ...
- ASP.NET没有魔法——ASP.NET MVC 路由的匹配与处理
ASP.NET MVC的路由是MVC应用的一个核心也是MVC应用处理的入口,作为一个开发者,在正常情况下仅仅需要做的就是根据需求去定义实体.业务逻辑,然后在MVC的Controller中去调用.Vie ...
- ASP.NET没有魔法——ASP.NET MVC IoC
之前的文章介绍了MVC如何通过ControllerFactory及ControllerActivator创建Controller,而Controller又是如何通过ControllerBase这个模板 ...
- ASP.NET没有魔法——ASP.NET MVC使用Oauth2.0实现身份验证
随着软件的不断发展,出现了更多的身份验证使用场景,除了典型的服务器与客户端之间的身份验证外还有,如服务与服务之间的(如微服务架构).服务器与多种客户端的(如PC.移动.Web等),甚至还有需要以服务的 ...
- ASP.NET没有魔法——ASP.NET MVC Razor与View渲染
对于Web应用来说,它的界面是由浏览器根据HTML代码及其引用的相关资源进行渲染后展示给用户的结果,换句话说Web应用的界面呈现工作是由浏览器完成的,Web应用的原理是通过Http协议从服务器上获取到 ...
- ASP.NET没有魔法——ASP.NET MVC Razor与View渲染 ASP.NET没有魔法——ASP.NET MVC界面美化及使用Bundle完成静态资源管理
ASP.NET没有魔法——ASP.NET MVC Razor与View渲染 对于Web应用来说,它的界面是由浏览器根据HTML代码及其引用的相关资源进行渲染后展示给用户的结果,换句话说Web应用的 ...
- ASP.NET没有魔法——ASP.NET MVC 与数据库大集合
ASP.NET没有魔法——ASP.NET与数据库 ASP.NET没有魔法——ASP.NET MVC 与数据库之MySQL ASP.NET没有魔法——ASP.NET MVC 与数据库之ORM ASP.N ...
- ASP.NET没有魔法——ASP.NET 身份验证与Identity
前面的文章中为My Blog加入了文章的管理功能(ASP.NET没有魔法——ASP.NET MVC使用Area开发一个管理模块),但是管理功能应该只能由“作者”来访问,那么要如何控制用户的访问权限?也 ...
随机推荐
- PHP中include与require的特点和区别说明
引用文件的方法有两种:require 及 include.两种方式提供不同的使用弹性. require 的使用方法如 require("MyRequireFile.php"); . ...
- webpack2使用ch6-babel使用 处理es6 优化编译速度
1 目录结构 安装依赖 cnpm install --save-dev babel-loader babel-core babel-preset-env babel-preset-latest &qu ...
- (转载)RESTful架构风格下的4大常见安全问题
转载自<RESTful架构风格下的4大常见安全问题>,作者:马伟 伴随着RESTful架构风格的大量应用微服务架构的流行,一些本来难以察觉到的安全问题也逐渐开始显现出来.在我经历过的各种采 ...
- 聊聊VUE中的nextTick
在谈nextTick之前,先要说明一件事,可能在我们平时使用vue时并没有关注到,事实上,vue执行的DOM更新是异步的. 举个栗子: <template> <div class=& ...
- Shell一个文件并等待完成
Option Explicit Private Declare Function OpenProcess Lib "kernel32" _ (ByVal dwDesiredAcce ...
- Laplace(拉普拉斯)先验与L1正则化
Laplace(拉普拉斯)先验与L1正则化 在之前的一篇博客中L1正则化及其推导推导证明了L1正则化是如何使参数稀疏化人,并且提到过L1正则化如果从贝叶斯的观点看来是Laplace先验,事实上如果从贝 ...
- Emgu.CV(一)
由于这块的知识不少,会分好几期写完 什么是OpenCV? OpenCV是一个基于(开源)发行的跨平台计算机视觉库,可以运行在Linux.Windows和Mac OS操作系统上.它轻量级而且高效--由一 ...
- win10 UWP Hmac
HMAC是密钥相关的哈希运算消息认证码,输入密钥和信息. 在uwp,Hmac在很多网络使用,我最近写qiniu SDK,把原来C#改为UWP,需要使用HMAC. 上传文件 <form metho ...
- MySql入门(1)
MySql入门(1) 安装 检查系统中是否已经安装了MySQL sudo netstat -tap | grep mysql 若没有显示已安装结果,则没有安装.否则表示已经安装. sudo apt-g ...
- elasticsearch+kibana+metricbeat安装部署方法
elasticsearch+kibana+metricbeat安装部署方法 本文是elasticsearch + kibana + metricbeat,没有涉及到logstash部分.通过beat收 ...