谈MVC运行机制,源码剖析

MVC整体运行机制:

 

首先我们在浏览器段输入网址:http://www.sina.com/news/society/1,回车。浏览器会通过DNS解析器,解析出域名的对应IP地址,通过IP地址连接到对应的主机的服务器。

连接服务器后,服务器首先会调用扩展程序ASPNET_ISAPI.dll进行处理,之后会调用这个程序集里的IsAPIRuntime类,创建一个HttpWorkRequest对象,内部存放有请求报文源信息.

 

HttpWorkerRequest对象内部一览

接着执行HttpRuntimeProcessRequest方法,将HttpWorkRequest作为参数创建HttpContext对象,HttpContextInit方法会通过对象创建HttpResponse,HttpRequestSessionServer等对象。

 

接着执行HttpApplicationFactoryInit方法:

1.确保网站第一次访问时调用了Global文件里的Application_Start方法;

 

 

2.获取Global文件里的类型作为网站的HttpApplication

3.每次返回一个HttpApplication类或子类的对象;

a) 创建系统配置文件及用户配置的HttpModule对象,FrameWork4的系统配置文件中添加了一个HttpModuleUrlRoutingModule.循环调用Init方法,为app对象里面的某些方法事件注册方法(向请求管道里的事件注册用户的代码,完成AOP编程)

执行HttpApplicationProcessRequest方法,内部执行“管道事件”.

当执行到执行第七个“管道事件”,创建一个MvcHanlder,存入HttpContent

RouteData routeData = this.RouteCollection.GetRouteData(context);

1.判断浏览器URL是否有服务器文件对应,如果有,则停止方法,继续执行后面的“管道事件”,(因为js/css/jpg等不需要经过mvc处理);

2.根据url到路由表里查找匹配url规则的路由。

a) 遍历路由表(RouteCollection)里的所有路由,元素类型为Route,并调用每个Route对象的GetRouteData方法。

 

b) GetRouteData方法中创建了一个RouteData对象,并将RouteMvcRouteHandler对象传进去

i. RouteData data=new RouteData(this,this.RouteHandler)this就是Route对象,调用ProcessConstraints检查约束,如果URL不满足约束的话,直接返回Null,停止方法执行,最后将Route对象里的URL默认值和命名空间存入RouteData中,最后返回RouteData对象。

3..接着执行RequestContext requestContext =new RequestContext(context,routeData);创建MvcHandler,并将RequestContext存入。

IHttpHandle httpHandler=routeHandler.GetHttpHandler(requestContext);

a) 执行routeData.GetHttpHandler方法,获取一个MvcHandler对象

b) context.RemapHandler(httpHandler);

其实就是将MvcHandler存入了HttpContext对象。

当执行到第八个事件的时候:首先会检查HttpContext里的remapHanlder,发现不为空,所以不再根据url创建页面对象,直接略过,执行后面的事件。

接着调用MvcHandlerProcessRequest方法:

1.创建被请求的Controll类的对象,并调用里面对应的Action方法;

2.找到视图引擎,创建对应的视图对象,视图引擎解析视图,生成Html代码。

接着获取控制器的名称:

1.string requiredString =this.RequestContext.RouteData.GetRequiredString(“controller”)

2.获取一个控制器工厂对象:

Factory =this.ControllerBuilder.GetControllerFactory();

3.通过工厂,创建被请求的控制器类对象。

Controller=factory.CreateController(this,RequestContext,requiredString)

4.调用控制器父类ControllerBase里的Excute方法

Controller.Excute(this,RequestContext);

4.1将上下文对象设置给ControllerContext(requestContext,this);

4.2 调用控制器里的Action方法

 

2.开始执行ViewResultBaseExcuteResult方法,这个方法要做的是:找到视图引擎,找到视图,执行视图生成html代码。

a) 先检查是否传入指定的视图名称,如果没有传入,则取Action方法的名字作为待会要读取的【视图名字】

If(string.IsNullOrEmpty(this.ViewName)).this.ViewName=Context.RouteData.GetRequiredString(“action”);

b) 找到对应的视图引擎

ViewEngineResult result=this.FindView(context,base.ViewName,this.MasterName);

c) 找到了RazorViewEngine对象之后,将会:

i. 调用试图引擎的FindView方法,但这个方法在RazorViewEngine类中没有,而是在父类中定义继承关系:

RazorViewEngine->BuildManagerViewEngine->VirtualPathProviderViewEngine

获取控制器名称,视图的路径:

String controllerName=controllerContext.RouteData.GetRequiredString(“controller”);

String virePath=GetPath(controllerContext,ViewLocationFormats,AreaViewLocationFormats,”ViewLocationFormats”,viewName,controllerName,_cacheKeyPrefic_View,useCache,out viewLocationSearched);

同时,还获得了母板页/布局页的路径

另一种情况:

Return  new ViewEngineResult(CreateView(controllerContext,viewPath,masterPath),this);

返回ViewEngineResult中就包含了这个RazorView对象了。

 

3.最终返回ViewEngineResult

4.获取返回的ViewEngineResult里的View对象,然后调用它的Render方法来生成html代码并写入Response中。

 

 

最后生成Html代码

 

 

posted @ 2012-12-01 20:44  虔城墨客  阅读(504)  评论(1编辑  收藏  举报