上篇文章从整体上介绍了ASP.NET MVC的请求处理流程,大概分为“路由”、“控制器”、“视图”以及“模型”,下面便按照流程依次展开。
一、路由
提到路由,实际上分为ASP.NET的核心路由引擎和MVC路由。核心路由引擎是不开源的(微软留了一手),它负责解析浏览器端传来的URL,并为之分配控制器。
这里我们要分析的是MVC路由,即MvcRouteHandler,该类显式实现了IRouteHandler接口,它的GetHttpHandler方法返回了一个MvcHandler对象,而MvcHandler实现了IHttpHandler接口,所以它包含一个ProcessRequest方法,如下:
代码段1
这个ProcessRequest方法相信大家都会觉得脸熟吧?不错,我们在ASP.NET WebForm开发中,经常会用到一般处理程序,即.ashx文件,这个文件中的类就实现了IHttpHandler接口,也有一个ProcessRequest方法。
好了,这个ProcessRequest方法就是路由定位到控制器后,执行的核心操作。也就是说,controller.Execute(RequestContext)语句的执行,导致了HTML响应的生成及回送浏览器。简单吧?我们在这里只是提到了最核心、最骨架的部分,没有涉及细节,为的就是不让大家被细枝末节所干扰。接下来就该分析控制器了。
二、控制器
代码段1中的controller是接口IController的一个实例,而接口IController很简单,只有一个方法如下:
代码段2
Controller的实例化是由【ProcessRequestInit(httpContext, out controller, out factory)】这个语句完成的,下面我们看一下ProcessRequestInit这个方法中实例化Controller的部分,不考虑细节,直奔主题。
代码段3
代码段3中的【controller = factory.CreateController(RequestContext, controllerName)】语句,就是实例化控制器的地方,这里根据路由系统定位的控制器信息(即我们在Controller文件夹中定义的各个控制器类),利用反射创建控制器对象。当然,这里面还有很多实现细节,比如控制器工厂、请求验证等,为了保持脉络清晰,在此略过,下文再谈。
IController接口在MVC中有若干个内置的实现类,包括ControllerBase以及IAsyncController,而Controller是ControllerBase的子类,是我们最常用的控制器基类。
其实,我们完全可以自己实现IController,例如:
代码段4
怎么样?So Easy!完全可以不用什么高大上的Razor引擎之类的东东。但是这样做会导致极强的耦合,我们需要自己解析拼接HTML,这可是个累人的活儿。
我们还是看看MVC的Controller类是怎么实现的吧。Controller继承于ControllerBase类,ControllerBase实现了Execute方法(代码段5),而Controller重写了ControllerBase的ExecuteCore方法(代码段6)。
代码段5
代码段6
我们看一下ExecuteCore方法,其核心语句是【if (!ActionInvoker.InvokeAction(ControllerContext, actionName))】,这条语句就是执行某个具体Action的地方,该语句执行完后,HTTP响应就被发回了浏览器。这里用到了ActionInvoker.InvokeAction方法,其中的ActionInvoker是IActionInvoker接口的实例,该接口定义也相当简单,如下:
代码段7
MVC内置的IActionInvoker实现类有ControllerActionInvoker和IAsyncActionInvoker,后者是异步类,先不管它,这里我们重点分析一下ControllerActionInvoker。
ControllerActionInvoker的InvokeAction方法实现较为复杂,有大概90行代码。今天有点累了,明天继续。