深入理解ASP.NET MVC(5)
回顾
系列的前4节深入剖析了ASP.NET URL路由机制,以及MVC在此基础上是如何实现Areas机制的,同时涉及到inbound和outbound很多细节部分。第2节中提到MvcRouteHandler是MVC框架的入口,这节开始,从MvcRouteHandler往下说开去。
Controller的创建过程:Builder和Factory
MvcRouteHandler的实现仅仅是通过GetHttpHandler方法返回一个MvcHandler实例,MvcHandler从RouteData中获得controller名字负责创建一个ControllerBuilder的实例,并通过ControllerBuilder的GetControllerFactory返回一个IControllerFactory的实例,这个实例就是DefaultControllerFactory,它的 CreateController方法负责创建需要的Controller实例。下面这段代码来自MvcHandler:
|
1
2
3
4
5
|
// Get the controller typestring controllerName = RequestContext.RouteData.GetRequiredString("controller");// Instantiate the controller and call Executefactory = ControllerBuilder.GetControllerFactory();controller = factory.CreateController(RequestContext, controllerName); |
DefaultControllerFactory创建Controller分两步:
|
1
2
|
Type controllerType = GetControllerType(requestContext, controllerName);IController controller = GetControllerInstance(requestContext, controllerType); |
GetControllerInstance最终是这样创建controller的:
|
1
|
return (IController)Activator.CreateInstance(controllerType); |
这就使得要使用DI设计模式十分困难。好在我们可以重写GetControllerInstance,并应用各种DI。受书中的影响,个人使用的是Ninject。
另外,为了加快GetControllerType方法,DefaultControllerFactory内部运用缓存机制将当前程序和所有引用程序集的类型缓存成哈希表。
还可以通过如下方法,提供某些名字空间较高的优先级来优化搜索。
|
1
2
3
4
5
6
|
protected void Application_Start() { RegisterRoutes(RouteTable.Routes); ControllerBuilder.Current.DefaultNamespaces.Add("MyApp.Controllers.*"); ControllerBuilder.Current.DefaultNamespaces.Add("OtherAssembly.MyNamespace.*"); } |
上面这种设置名字空间的优先级仍然低于在设置路由表时为某个路由指定的名字空间,Areas机制就是靠在设置路由表时指定名字空间实现的,详见深入理解ASP.NET MVC(4)。
也可以在ControllerBuilder层面上替换ControllerFactory:
|
1
2
3
4
5
|
protected void Application_Start() { RegisterRoutes(RouteTable.Routes); ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory()); } |
Controller的调用:Controller只是普通的.NET类
MvcHandler依靠ControllerBuilder和IControllerFactory获得Controller的实例后,调用Controller实例的Execute方法,在该方法返回后再调用IControllerFactory的ReleaseController收尾。由此看出Controller的Execute做了所有的事情,看似“功能强大”,其实它只是.NET的普通类, MVC框架赋予其“非凡”的能力:
所有的Controller只要实现一个接口,IController,接口的定义了Execute方法:
|
1
2
3
4
5
6
7
|
namespace System.Web.Mvc { using System.Web.Routing; public interface IController { void Execute(RequestContext requestContext); }} |
从接口定义可以看出,当Controller被“调用”的时候,应该负责完成Execute方法,参数RequestContext封装了HttpContext,所以可以像下面这样直接实现一个Controller,同样可以工作:
|
1
2
3
4
5
6
7
|
public class HelloWorldController : IController { public void Execute(RequestContext requestContext) { requestContext.HttpContext.Response.Write("Hello, world!"); } } |
然而,需要的逻辑和架构远比这个复杂的多,因此MVC框架提供了如下类关系:
IController->ControllerBase->Controller
其中ControllerBase实现Execute,Execute在内部调用ExecuteCore,ExecuteCore作为一个抽象方 法,延迟到Controller中实现。ControllerBase只提供了诸如TempData、ViewData等,Controller的 ExecuteCore方法真正invoke了action机制,是action的入口。下面的代码是ExecuteCore的实现:
|
1
2
3
4
5
6
7
8
9
10
|
PossiblyLoadTempData();try { string actionName = RouteData.GetRequiredString("action"); if (!ActionInvoker.InvokeAction(ControllerContext, actionName)) { HandleUnknownAction(actionName); } } finally { PossiblySaveTempData(); } |
可以看到RouteData在这里又提供了action参数,可以想象InvokeAction方法依靠这个action的名字调用action,并实现诸多验证机制。下节开始讨论action逻辑。
劳动果实,转载请注明出处:http://www.cnblogs.com/P_Chou/archive/2010/11/20/details-asp-net-mvc-05.html
深入理解ASP.NET MVC(5)的更多相关文章
- 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC
系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递 七天学会ASP.NET MVC (三)— ...
- [转载]深入理解ASP.NET MVC之ActionResult
Action全局观 在上一篇最后,我们进行到了Action调用的“门口”: 1 if (!ActionInvoker.InvokeAction(ControllerContext, actionNam ...
- 深入理解ASP.NET MVC Day1
深入理解ASP.NET MVC ASP.NET vs MVC vs WebForms 许多ASP.NET开发人员开始接触MVC认为MVC与ASP.NET完全没有关系,是一个全新的Web开发,事实上 ...
- 七天学会ASP.NET MVC ——深入理解ASP.NET MVC
七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会ASP.NET MVC (二) ...
- 深入理解ASP.NET MVC(6)
系列目录 Action全局观 在上一篇最后,我们进行到了Action调用的“门口”: 1 if (!ActionInvoker.InvokeAction(ControllerContext, acti ...
- 深入理解ASP.NET MVC(目录)
学ASP.NET MVC2有一段时间了,也针对性的做了个练习.感觉这个框架还是不错的,所以决定要深入系统的学习一下.看到这样一本书: 作者博客:http://blog.stevensanderson. ...
- 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 【转】
http://www.cnblogs.com/powertoolsteam/p/MVC_one.html 系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会A ...
- [转载] ASP.NET MVC (一)——深入理解ASP.NET MVC
个人认为写得比较透彻得Asp.net mvc 文章,所以转载过来,原文链接在最后: ASP.NET vs MVC vs WebForms 许多ASP.NET开发人员开始接触MVC认为MVC与ASP.N ...
- 理解ASP.NET MVC的路由系统
引言 路由,正如其名,是决定消息经由何处被传递到何处的过程.也正如网络设备路由器Router一样,ASP.NET MVC框架处理请求URL的方式,同样依赖于一张预定义的路由表.以该路由表为转发依据,请 ...
随机推荐
- 推荐内置android控件的开源项目alcinoe
开源地址:https://github.com/Zeus64/alcinoe 该控件包,含以下几个控件: 1.基于OpenGL实现的视频播放器 ALVideoPlayer. ALVideoPlayer ...
- git 清空缓冲区
git rm与git rm --cached 当我们需要删除暂存区或分支上的文件, 同时工作区也不需要这个文件了, 可以使用 git rm file_path git commit -m 'delet ...
- 17 多校1 Add More Zero 水题
Problem Description There is a youngster known for amateur propositions concerning several mathemati ...
- 解决react-native软键盘弹出挡住输入框的问题
解决react-native软键盘弹出挡住输入框的问题 写登录页面,整体界面居中之后就出现软键盘弹出挡住输入框,用户体验不好的情况.用了RN官方的KeyboardAvoidingView组件,会有多出 ...
- ubuntu discuz 该函数需要 PHP 支持 XML。请联系空间商,确定开启了此项功能
apt-get install php-xml apt-get install php-xml-parser
- Python之路PythonNet,第三篇,网络3
pythonnet 网络3 udp 通信 recvfrom sendtofork 多进程并发threading 多线程并发socketserver 系统模块 套接字的属性 setsockopt g ...
- Micro- and macro-averages
https://datascience.stackexchange.com/questions/15989/micro-average-vs-macro-average-performance-in- ...
- HPU1460: 杨八方的表面兄弟
题目描述 如果你之前关注过HPUOJ的话,那么你一定听说过杨八方的名字.在去年,很多同学共同见证了杨八方同学的填报志愿.来到学校.军训--或许你曾陪同杨八方一起思考过许多问题,又或者你是刚听说这个名字 ...
- C++学习(十八)(C语言部分)之 指针2
指针1.指针的概述 指针是什么? 指针是一个地址 是一个常量 int 整型 int a a是变量 指针用来做什么? 方便使用数组或者字符串 像汇编语言一样处理内存地址2.指针变量 什么是指针变量? 是 ...
- hdu4300 Clairewd’s message 扩展KMP
Clairewd is a member of FBI. After several years concealing in BUPT, she intercepted some important ...