ASPNETMVC整体运行原理走源码.docx
《ASPNETMVC整体运行原理走源码.docx》由会员分享,可在线阅读,更多相关《ASPNETMVC整体运行原理走源码.docx(20页珍藏版)》请在冰点文库上搜索。
ASPNETMVC整体运行原理走源码
MVC那些不为人知的一些事情
有好些理解是直接写在源码里的,然后通过截图,放到这个Word里面,所以图很重要,有图有证据嘛。
有些不清晰的,就放大来看啦(Ctrl+滚轮上)哈哈···
MVC运行的整体机制整体路线:
浏览器发送请求
IIS捕获到请求,根据请求里面的信息找到对应的程序集
加载程序集,创建运行环境
包装请求信息(wr)
调用HttpRuntime的PR方法创建application(读取global文件,调用Application_Start方法)
初始化(读取配置文件(用户+系统的),调用InitModlues()方法),第七个事件里注册了UrlRoutingModules方法
创建MvcHandler,它包含了请求上下文信息,路由信息,并将其添加到上下文HttpContext
调用MvcHandler的PR方法,创建控制器,调用action(用户在Controller下面写的方法),将用户数据保存到父类里面。
执行action返回ViewResult(包含了用户执行后的数据)
拿取视图引擎,调用Render()方法,生成Html代码,创建视图。
能力有限,没求甚解。
愿互相学习,互相指正,共同进步。
【你必须非常努力,才能看起来毫不费力!
】
ASP.NET和MVC.NET的区别从UrlRoutingModules这个方法说起。
.NET程序运行的时候,会先执行初始化,也就是调用Global文件里的Application_Start方法。
通过反射创建这个文件里的类(在ASP.NET里面就是Global类,在MVC下是MVCApplication类,它们继承自HttpApplication类。
)如果Global文件不存在,就直接创建他们的父类:
HttpApplication。
接着在确保调用了Application_Start方法后,创建ApplicationInstance实例(对象池),然后进行初始化。
在.NETFrameWork4.0,初始化时读取配置文件web.config(包括系统配置文件和用户自定义的配置文件)。
在系统配置文件下有一个HttpModules。
内容如下:
读取HttpModules节点,为其创建对应的对象,循环调用里面的Init方法,在这个方法里,向application里面的事件注册方法(用户的代码)。
完成AOP编程。
MVC在配置文件里,写了一个UrlRoutingModule,创建这个方法,在这个方法里的Init方法里,向管道事件的第七个事件注册了一个方法。
这个方法主要做的是将MVCHandler添加到上下文中(HttpContext).【下面这个图是从浏览器请求开始的】
那么要研究MVC就从这个UrlRoutingModule(继承IHttpModule接口)方法开始研究。
UrlRoutingModule类下的Init()方法在第七个事件下注册了一个方法:
这个方法里:
1、拿到HttpApplication对象,
2、将上下文对象HttpContext封装到HttpContextBase里面。
3、传入上下文对象,执行事件。
---------------------------------------------------------分割线------------------------------------------------------
1、拿取路由数据。
1.1根据上下文,进行过滤,判断请求的是不是一个已经存在的文件,如果是,则直接返回这个文件。
1.2如果请求的不是存在的文件,那么获取路由数据。
获取路由数据的时候,调用的是RouteBase类下面的GetRouteData(httpContext)方法。
1.2.1RouteBase下的GetRouteData方法,但是,实现这个方法的类是Route。
继续看GetRouteData()方法:
因为在Reflector下不能写注释,我转到了MVC源码下面。
到这里,是时候说明一下那个RouteHandler是哪里来的了。
其实它就是MVCRouteHandler。
我们到Global文件下去看。
A:
这里注册路由,调用MvcApplication下的RegisterRoutes方法。
即B
B:
将路由信息传入到MapRoute下面,它其实就是返回一个Route对象回来。
具体做了什么呢?
上面我在1.2.2那里标记了一下,那个就是Route类的一个构造函数
Route(stringurl,IRouteHandlerrouteHandler),
然后在这里new了一个Route对象,并传入了一个url和一个MvcRouteHandler对象,因此,到这里,可以知道routeHandler就是MvcRouteHandler。
而上面已经确定了,this就是Route,那么Route下的RouteHandler也就是MvcRouteHandler。
参看1.2.3!
在1.2.2里将routeHandler传给1.2.3的RouteHandler。
我们接着说GetRouteData()方法。
简单地说,GetRouteData就是拿取路由数据,将MvcRouteHandler添加到RouteData对象里
RouteDatadata=newRouteData(this,this.RouteHandler).但是在里面做了一些检查,检查路径,检查约束。
最后返回这个data。
还是看一下RouteData里面的内容吧:
这里面包含了MvcRouteHandler(RouteHandler),命名空间(dataTokens),路由数据?
没去研究RouteValueDictionary()。
反正这里包含了我们传进来的路由信息。
保存在RouteCollection集合里面。
提一下:
RouteTable里也一个RouteCollection,静态的,是为了能够在整个生命周期里面使用到路由数据。
如下图:
接着我们继续看第二部分吧。
2、在第一部分里,已经将MvcRouteHandler添加到了routeData里面,返回一个data对象。
而MvcRouteHandler最后传递为RouteHandler。
第二部分:
IRouteHandlerrouteHandler=routeData.RouteHandler;从routeData里面获取到routeHandler对象。
为什么是IRouteHandler类型呢?
擦,因为从Route构造函数开始就是IRouteHandler类型定义来接收的····
接着看第三部分
3、RequestContextrequestContext=newRequestContext(context,routeData);
context.Request.RequestContext=requestContext;
将context对象和上面拿到的路由数据routeData封装到RequestContext里面,然后赋值给HttpContextBase下的HttpRequestBase的requestContext属性。
也就是将路由数据和封装过的上下文信息再添加到上下文里面。
IHttpHandlerhttpHandler=routeHandler.GetHttpHandler(requestContext);
GetHttpHandler(requestContext)这里返回一个MvcHandler。
然后我们去MvcHandler下去看看,还是不看先,留到后面看吧。
应该就是调用PR方法执行后面一系列流程了。
留待后面揭秘。
暂时知道GetHttpHandler方法里返回这个MvcHandler对象就行了。
接收类型是IhttpHandler接口!
!
!
!
!
!
!
!
!
熟悉啦~~
接着看第四部分,也是在第七个事件里注册的方法执行的最后一步。
context.RemapHandler(httpHandler);
这个方法是把获得的那个MvcHandler添加到上下文对象中。
这个方法具体做啥先。
先得说一下,在第三部分的时候,已经将context传进了HttpContextBase里。
待会用到HttpContextWrapper,它继承HttpContextBase,重写了HttpContextBase里面的ReMapHandler方法。
。
。
。
详细见图:
好了,进入ReMapHandler方法:
Typetype=handler.GetType();//获得类型:
MvcHandler
handlerType=type.AssemblyQualifiedName;//获得当前类型在程序集里面的名字:
System.web.MVC.MvcHandler
handlerName=type.FullName;//获得全名
this._remapHandler=handler;//将MvcHandler添加到上下文对象中,这里的this就是HttpContext
在第七个事件里注册的方法,最终就是拿到路由数据,将创建的Handler添加到上下文中。
PostResolveRequestCache(HttpContextBasecontext)到此,运行完···接着深入。
在原来的ASP.NET的整个运行周期上,挑中合适的时机,弄出分叉来,然后MVC.net诞生了。
那么这个时机在哪里呢?
1、FrameWork4.0下会先读取系统配置文件,这个文件下的节点HttpModules里配置了一个UrlRoutingModule,在读取这个配置文件的时候,就会创建这个Module对象,创建方法,在初始化的时候在第七个事件PostResolveRequestCache里注册方法,这个方法里面封装上下文和路由信息,创建了MvcHandler并添加到上了下文里(HttpContex)。
2、在第八个事件(PostMapRequestHandler)执行时(是不是在执行的时候检查呢?
还是在执行之前检查?
这个还没有考证!
),会先判断上面的那个_remapHandler是不是空的,如果不空(MVC执行程序),就不再创建页面类对象,直接返回Handler。
否则根据请求路径创建页面类对象······等执行ASP.NET运行机制。
以上两个时机造就了MVC。
在创建的MvcHandler里有我们最常见的PR(ProcessRequest)方法.
现在开始揭秘MvcHandler到底干了什么。
(只研究主要的)
在ASP.net整个运行的管道第九个事件里要拿到请求的Session,会检查当前请求的类是否实现了IRequiresSessionState接口。
再看MvcHandler类,
它已经实现了这个接口!
其实,这个MvcHandler就相当于是一个页面类对象。
可以自己去该类下面看看。
跟ASP.NET一样,在第十一和十二个事件之间会调用页面类对象的PR方法,ASP.NET里调用page(继承自IHttpHandler)类的PR(是实现IHttpHandler的)方法。
在Mvc.Net里则调用MvcHandler(也继承自IHttpHandler)里的PR(也是实现IHttpHandler的)方法。
老样子,进入PR方法:
1、创建一个控制器接口对象,在初始化的时候为其赋值。
创建控制器!
根据拿到的控制器的类型,创建的行为是由工厂完成的!
工厂在这里起到的作用除了提供多态外,还提供一个对象池,每一次创建控制器的时候都会到这个池里面去检查。
在ProcessRequestInit()方法里面:
接着走下去,看CreateController()方法。
不做太多的解释了,到Create()方法,再到Activitor下的CreateInstance方法。
反正最终就是根据type创建出这个实例。
见下面两个图:
2、执行Execute()方法,这是一个很关键的方法。
在Initialize方法里:
(this就是ControllerBase)
主要看ExecuteCore()方法:
好啦,走到这里终于到了调用Action了。
在Action里面会存在一些与视图相关的东西。
因此在action里面要创建视图(View()方法),设置数据,返回ViewResult···
从读取配置文件
在第七个事件里注册方法,创建MvcHandler,将路由信息和请求上下文信息传进去
MvcHandler为类页面类对象,调用里面的PR方法,通过反射创建controller对象,调用里面的Action。
Action就是我们平时直接写代码的方法。
返回一个ActionResultreturnView();
So
接下来研究Action,是怎么创建视图返回的,又是怎样设置保存后台数据等等···
1、执行程序员的action方法,返回ActionResult:
ViewResult就是authContext.Result。
这些数据保存到HomeController的父类的父类ControllerBase里面,然后再在Controller类里面new了一个ViewResult,执行action的时候就返回这个ViewResult,将这些数据传递保存到ViewResultBase里面,以供创建视图的时候使用!
2、拿到ViewResult并保存到AuthContext里面(authContext.Result),开始执行ExecuteResult()方法!
1、FindView(context):
1.1
1.1.1
1.1.1.1
找RazorViewEngine:
最终找到了FindView啦····
在FindView返回关联本地视图的引擎(啥?
不懂),有母版页的时候的!
或者创建一个新的视图引擎····CreateView()
在RazorViewEngine下面找到了CreateView()
So
拿到了视图引擎了,PublicIViewView{set;get;}已经赋值,
那么在Render()方法里面生成Html代码,并放入Response里····哈,整一条路线终于清晰啦。
MVC整个机制就到这里·····