asp.net MVC 应用程序的生命周期

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sD7O95O/article/details/78097481

  首先我们知道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

  先看看下面这张图,描述了请求管道中的控件和所扮演的角色:

640?wx_fmt=png

  上图就是一个完整的mvc应用程序的一个http请求到响应的整个儿所经历的流程。从UrlRoutingModule拦截请求到最终ActionResult执行ExecuteResult方法生成响应。

下面我们就来详细讲解一下这些过程都做了些什么。

 

UrlRoutingModule

640?wx_fmt=pngMVC应用程序的入口UrlRoutingModule

首先发起一个请求,会被UrlRoutingModule拦截。

640?wx_fmt=png

从上图中我们看到UrlRoutingModule实现了接口IHttpModule,所以UrlRoutingModule是一种HttpModule。在这之前,所有的请求还不确定是被谁处理。就是在这个UrlRoutingModule里,决定了这个request是否被MVC应用程序处理。UrlRouting module会从路由表中选择一个相匹配的路由规则。

640?wx_fmt=png

那么UrlRouting Module是如何选择匹配规则的呢?

640?wx_fmt=png

我们看看我们新建的MVC应用程序,在App_Start文件夹下面有一个RouteConfig.cs类,这个类的内容如下:

640?wx_fmt=png

  我们在这个类里面,主要是给路由表添加路由规则。在看看上面的UrlRoutingModule类,里面有一个RoutCollection属性,所以UrlRoutingModule能够获取路由表中的所有规则,这里值得注意的是,路由规则的匹配是有顺序的,如果有多个规则都能够匹配,UrlRoutingModule至选择第一个匹配的规则就返回,不再继续往下匹配了。相反的如果一个请求,没有匹配到任何路由,那么该请求就不回被处理。

RouteHandler

640?wx_fmt=png生成MvcHander

在上面路由匹配的过程中,与匹配路由相关联的MvcRouteHandler ,MvcRouteHandler 实现了IRouteHandler 接口。MvcRouteHandler 主要是用来获取对MvcHandler的引用。MvcHandler实现了IhttpHandler接口。

当MvcRouteHandler 被创建的时候,就会调用PostResolveRequestCache()方法。PostResolveRequestCache()方法的定义如下:

640?wx_fmt=png

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

640?wx_fmt=pngMvcHandler就是最终对request进行处理。

MvcHandler的定义如下:

640?wx_fmt=png

我们可以看到MvcHandler就是一个普通的Http  Handler.我们知道一个http handler需要实现一个ProcessRequest()的方法,这个方法就是处理request的核心。所以MvcHandler实现了ProcessRequest()方法。

ProcessRequest()定义如下:

640?wx_fmt=png

从上面的代码可以看出调用了一个ProcessRequestInit()方法,定义如下:

640?wx_fmt=png

ProcessRequestInit()方法中首先创建了ControllerFactory()的对象 factory.然后ControllerFactory创建了相关Controller的实例.最终调用了Controller的Excute()方法。

好我们再来看看ControllerFactory:

ControllerFactory

640?wx_fmt=png主要是用来生成Controller对象

ControllerFactory实现了接口IControllerFactory.

Controller

 到这里我们大概就知道了,MvcHandler通过ProcessRequest()方法最终创建了Controller对象,这里我们都应该知道,Controller里面包含很多的Action方法,每一次请求至少一个Action方法会被调用。为了明确的实现IController接口,框架里面有一个ControllerBase的类已经实现了IController接口,其实我们自己的Controller也可以不继承ControllerBase,只要实现IController接口即可。

 640?wx_fmt=png

controller对象实际上使用ActionInvoker来调用Action方法的,当Controller对象被创建后,会执行Controller对象的基类ControllerBase类里面的Excute方法。Excute方法又调用了ExcuteCore()方法。Controller类里面实现了ExcuteCore()方法。ExcuteCore调用了ActionInvoker的InvokerAction方法来调用Action方法。

ActionInvoker

ActionInvoker方法有很重要的责任来查找Controller中的Action方法并且调用。

640?wx_fmt=png

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接口即可。

640?wx_fmt=png

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输出响应。

总结:如果我们理解了整个过程中发生了什么,哪些类和哪些方法被调用,我们就可以在需要扩展的地方轻松的进行扩展。

原文地址:http://www.cnblogs.com/yplong/p/5582576.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

640?wx_fmt=jpeg

猜你喜欢

转载自blog.csdn.net/sD7O95O/article/details/78097481