系列目录

回顾

系列的前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 type
string controllerName = RequestContext.RouteData.GetRequiredString("controller");
// Instantiate the controller and call Execute
factory = 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)的更多相关文章

  1. 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC

    系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递 七天学会ASP.NET MVC (三)— ...

  2. [转载]深入理解ASP.NET MVC之ActionResult

    Action全局观 在上一篇最后,我们进行到了Action调用的“门口”: 1 if (!ActionInvoker.InvokeAction(ControllerContext, actionNam ...

  3. 深入理解ASP.NET MVC Day1

    深入理解ASP.NET MVC   ASP.NET vs MVC vs WebForms 许多ASP.NET开发人员开始接触MVC认为MVC与ASP.NET完全没有关系,是一个全新的Web开发,事实上 ...

  4. 七天学会ASP.NET MVC ——深入理解ASP.NET MVC

    七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC   系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会ASP.NET MVC (二) ...

  5. 深入理解ASP.NET MVC(6)

    系列目录 Action全局观 在上一篇最后,我们进行到了Action调用的“门口”: 1 if (!ActionInvoker.InvokeAction(ControllerContext, acti ...

  6. 深入理解ASP.NET MVC(目录)

    学ASP.NET MVC2有一段时间了,也针对性的做了个练习.感觉这个框架还是不错的,所以决定要深入系统的学习一下.看到这样一本书: 作者博客:http://blog.stevensanderson. ...

  7. 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 【转】

    http://www.cnblogs.com/powertoolsteam/p/MVC_one.html 系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会A ...

  8. [转载] ASP.NET MVC (一)——深入理解ASP.NET MVC

    个人认为写得比较透彻得Asp.net mvc 文章,所以转载过来,原文链接在最后: ASP.NET vs MVC vs WebForms 许多ASP.NET开发人员开始接触MVC认为MVC与ASP.N ...

  9. 理解ASP.NET MVC的路由系统

    引言 路由,正如其名,是决定消息经由何处被传递到何处的过程.也正如网络设备路由器Router一样,ASP.NET MVC框架处理请求URL的方式,同样依赖于一张预定义的路由表.以该路由表为转发依据,请 ...

随机推荐

  1. $_SERVER['URI']

    WordPress通过301重定向实现非首先域(非www)跳转向本来是一个很简单事情,由于没弄清楚$_SERVER['HTTP_X_REWRITE_URL'] 和$_SERVER['REQUEST_U ...

  2. 简短而有效的python queue队列解释

    Queue.qsize() 返回队列的大小  Queue.empty() 如果队列为空,返回True,反之False  Queue.full() 如果队列满了,返回True,反之False Queue ...

  3. HDU 6055 17多校 Regular polygon(计算几何)

    Problem Description On a two-dimensional plane, give you n integer points. Your task is to figure ou ...

  4. Git 创建分支与合并分支

    下面以branchName=>aiMdTest为例介绍 1.  下载code git clone masterUrl iva(另存文件名) 2.  创建并切换分支 cd iva git chec ...

  5. 20165228 2017-2018-2 《Java程序设计》第8周学习总结

    20165228 2017-2018-2 <Java程序设计>第8周学习总结 教材学习内容总结 进程与线程的关系 多线程的运行机制 线程的四种状态:新建.运行.中断.死亡 使用Thread ...

  6. Linux大文件分割splite

    /********************************************************************** * Linux大文件分割splite * 说明: * 编 ...

  7. Skflow mac安装 for tensorflow-0.8.0

    参考: # Mac OS X, CPU only: $ pip install --ignore-installed --upgrade https://storage.googleapis.com/ ...

  8. GitHub使用教程、注册与安装

    GitHub注册与安装 本文提供全流程,中文翻译.Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请调整网页缩放比例至200%) 1 进入GitHub官网:http ...

  9. 改变html中的内容

    $("#id").html()            获取内容 $("#id").html(xiugai)    修改内容

  10. xdoj 1028 (素数线性筛+dp)

    #include <bits/stdc++.h> using namespace std; ; int prime[N]; int dp[N]; int main () { memset ...