asp.net MVC 应用程序的生命周期
Posted dotNET跨平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了asp.net MVC 应用程序的生命周期相关的知识,希望对你有一定的参考价值。
首先我们知道http是一种无状态的请求,他的生命周期就是发出请求开始,到得到响应结束。那么MVC应用程序从发出请求到获得响应,都做了些什么呢?
本文我们会详细讨论MVC应用程序的生命周期和一个请求,从一个控件到另一个控件是怎样被处理的。我们还会详细介绍一下整个请求的生命周期中,用到的相关组件。在平常的开发过程中,我们可能知道怎样去使用MVC框架来处理相关的请求,大部分的时候我们只是在controller和action方法之间做相关的处理。
当我最开始学习使用mvc的时候,困扰我的一个问题就是,一个请求的流程控制是怎样的呢?从view到controller再到action之间经历了什么?那个时候我还不清楚HTTP module和HTTP handler在处理一个请求中扮演什么样的角色,起什么样的作用呢。毕竟MVC是一个web开发框架,肯定包含了http module和http handler在整个请求过程中。其实还有很多相关的组件包含在一个完整的mvc应用程序请求生命周期里,在整个请求过程中他们都扮演者非常重要的角色。尽管大部分时候我们都使用的是框架提供的默认的函数,但是如果我们了解了每个控件所扮演的角色,我们就可以轻松的扩展和使用我们自己实现的方法,就目前来说MVC是扩展性比较强的框架。下面是本章节的主要内容:
UrlRoutingModule
RouteHandler
MvcHandler
ControllerFactory
Controller
ActionInvoker
ActionResult
ViewEngine
先看看下面这张图,描述了请求管道中的控件和所扮演的角色:
上图就是一个完整的mvc应用程序的一个http请求到响应的整个儿所经历的流程。从UrlRoutingModule拦截请求到最终ActionResult执行ExecuteResult方法生成响应。
下面我们就来详细讲解一下这些过程都做了些什么。
UrlRoutingModule
MVC应用程序的入口UrlRoutingModule
首先发起一个请求,会被UrlRoutingModule拦截。
从上图中我们看到UrlRoutingModule实现了接口IHttpModule,所以UrlRoutingModule是一种HttpModule。在这之前,所有的请求还不确定是被谁处理。就是在这个UrlRoutingModule里,决定了这个request是否被MVC应用程序处理。UrlRouting module会从路由表中选择一个相匹配的路由规则。
那么UrlRouting Module是如何选择匹配规则的呢?
我们看看我们新建的MVC应用程序,在App_Start文件夹下面有一个RouteConfig.cs类,这个类的内容如下:
我们在这个类里面,主要是给路由表添加路由规则。在看看上面的UrlRoutingModule类,里面有一个RoutCollection属性,所以UrlRoutingModule能够获取路由表中的所有规则,这里值得注意的是,路由规则的匹配是有顺序的,如果有多个规则都能够匹配,UrlRoutingModule至选择第一个匹配的规则就返回,不再继续往下匹配了。相反的如果一个请求,没有匹配到任何路由,那么该请求就不回被处理。
RouteHandler
生成MvcHander
在上面路由匹配的过程中,与匹配路由相关联的MvcRouteHandler ,MvcRouteHandler 实现了IRouteHandler 接口。MvcRouteHandler 主要是用来获取对MvcHandler的引用。MvcHandler实现了IhttpHandler接口。
当MvcRouteHandler 被创建的时候,就会调用PostResolveRequestCache()方法。PostResolveRequestCache()方法的定义如下:
PostResolveRequestCache()方法主要做的工作如下:
1、PostResolveRequestCache()是在UrlRoutingModule类里面,UrlRoutingModule类里面有一个RoutCollection属性,而这个属性有一个GetRouteData()方法,
我们看到PostResolveRequestCache()方法中恰好调用了GetRouteData()这个方法,然后返回了一个RouteData对象。
2、RouteData里面有一个IRouteHandler类型的属性RouteHandler ,而调用GetRouteData()返回的RouteData对象里的RouteHandler就是MvcRouteHandler。
3、MvcRouteHandler类有一个GetHttpHandler方法,返回的是一个IHttpHandler类型的对象,返回的就是对MvcHandler对象的引用,绑定到一个MvcHandler的实例。
下面我们就看看MvcHandler做了些什么:
MvcHandler
MvcHandler就是最终对request进行处理。
MvcHandler的定义如下:
我们可以看到MvcHandler就是一个普通的Http Handler.我们知道一个http handler需要实现一个ProcessRequest()的方法,这个方法就是处理request的核心。所以MvcHandler实现了ProcessRequest()方法。
ProcessRequest()定义如下:
从上面的代码可以看出调用了一个ProcessRequestInit()方法,定义如下:
在ProcessRequestInit()方法中首先创建了ControllerFactory()的对象 factory.然后ControllerFactory创建了相关Controller的实例.最终调用了Controller的Excute()方法。
好我们再来看看ControllerFactory:
ControllerFactory
主要是用来生成Controller对象
ControllerFactory实现了接口IControllerFactory.
Controller
到这里我们大概就知道了,MvcHandler通过ProcessRequest()方法最终创建了Controller对象,这里我们都应该知道,Controller里面包含很多的Action方法,每一次请求至少一个Action方法会被调用。为了明确的实现IController接口,框架里面有一个ControllerBase的类已经实现了IController接口,其实我们自己的Controller也可以不继承ControllerBase,只要实现IController接口即可。
controller对象实际上使用ActionInvoker来调用Action方法的,当Controller对象被创建后,会执行Controller对象的基类ControllerBase类里面的Excute方法。Excute方法又调用了ExcuteCore()方法。Controller类里面实现了ExcuteCore()方法。ExcuteCore调用了ActionInvoker的InvokerAction方法来调用Action方法。
ActionInvoker
ActionInvoker方法有很重要的责任来查找Controller中的Action方法并且调用。
ActionInvoker是一个实现了IActionInvoker接口的对象:
bool InvokeAction( ControllerContext controllerContext, string actionName )
Controller类里面暴露了一个ActionInvoker 属性,会返回一个ControllerActionInvoker 。ActionInvoker通过CreateActionInvoker()方法来创建ControllerActionInvoker对象。
我们看到CreateActionInvoker()是一个Virtual方法,我们可以实现自己的ActionInvoker.
ActionInvoker类需要匹配Controller中详细的Action来执行,而这些详细的信息是由ControllerDescriptor 提供的。ControllerDescriptor 和ActionDescriptor在ActionInvoker中扮演重要的角色。这两个分别是对Controler和Action的详细描述。ControllerDescriptor 描述了Controller的相关信息比如name,action,type等。
ActionDescriptor 描述了Action相关的详情,比如name,controller,parameters,attributes和fiflters等。
ActionDescriptor 中一个中要的方法就是FindAction(),这个方法返回一个ActionDescriptor 对象,所以ActionInvoker知道该调用哪个Action。
ActionResult
到目前为止,我们看到了Action方法被ActionInvoker调用。所有的Action方法有一个特性,就是返回一个ActionResult类型的数据。
public abstract class ActionResult { public abstract void ExecuteResult(ControllerContext context); }
ExecuteResult()是一个抽象方法,所以不同的子类可以提供不同的ExecuteResult()实现。
ActionResult执行后响应输出到客户端。
ViewEngine
ViewResult几乎是大部分应用程序的返回类型,主要通过ViewEngine引擎来展示view的。ViewEngine可能主要就是生成html元素的引擎。Framwork提供了2种引擎,Razor View Engine 和Web Form View Engine.如果你想自定义引擎,你可以创建一个引擎只要实现IViewEngine接口即可。
IViewEngine 有下面几个方法:
1、FindPartialView :当controller需要返回一个PartialView的时候,FindPartialView方法 就会被调用。
2、FindView
3、ReleaseView :主要用来有ViewEngine释放资源
ViewResultBase 和ViewResult是比较重要的两个类。ViewResultBase 包含下面的实现代码:
当ViewResult的方法ExecuteResult被调用后,ViewResultBase 的ExecuteResult 方法被调用,然后ViewResultBase 调用ViewResult的FindView 。紧接着ViewResult 返回ViewEngineResult,之后ViewEngineResult调用Render()方法来绘制html输出响应。
总结:如果我们理解了整个过程中发生了什么,哪些类和哪些方法被调用,我们就可以在需要扩展的地方轻松的进行扩展。
.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注
以上是关于asp.net MVC 应用程序的生命周期的主要内容,如果未能解决你的问题,请参考以下文章
[译] ASP.NET 生命周期 – ASP.NET 请求生命周期