admin 管理员组文章数量: 887173
2024年1月13日发(作者:时间戳格式化为时间)
MVC那些不为人知的一些事情
有好些理解是直接写在源码里的,然后通过截图,放到这个Word里面,所以图很重要,有图有证据嘛。有些不清晰的,就放大来看啦(Ctrl+滚轮上)哈哈···
MVC运行的整体机制整体路线:
浏览器发送请求
IIS捕获到请求,根据请求里面的信息找到对应的程序集
加载程序集,创建运行环境
包装请求信息(wr)
调用HttpRuntime的PR方法创建application(读取global文件,调用Application_Start方法)
初始化(读取配置文件(用户+系统的),调用InitModlues()方法),第七个事件里注册了UrlRoutingModules方法
创建MvcHandler,它包含了请求上下文信息,路由信息,并将其添加到上下文HttpContext
调用MvcHandler的PR方法,创建控制器,调用action(用户在Controller下面写的方法),将用户数据保存到父类里面。
执行action返回ViewResult(包含了用户执行后的数据)
拿取视图引擎,调用Render()方法,生成Html代码,创建视图。
能力有限,没求甚解。愿互相学习,互相指正,共同进步。
【你必须非常努力,才能看起来毫不费力!】
和的区别从UrlRoutingModules这个方法说起。
.NET 程序运行的时候,会先执行初始化,也就是调用Global文件里的Application_Start方法。
通过反射创建这个文件里的类(在里面就是Global类,在MVC下是MVCApplication类,它们继承自HttpApplication类。) 如果Global文件不存在,就直接创建他们的父类:HttpApplication。
接着在确保调用了Application_Start方法后,创建ApplicationInstance实例(对象池),然后进行初始化。
在.NETFrameWork 4.0,初始化时读取配置文件(包括系统配置文件和用户自定义的配置文件)。
在系统配置文件下有一个HttpModules。内容如下:
读取HttpModules节点,为其创建对应的对象,循环调用里面的Init方法,在这个方法里,向application里面的事件注册方法(用户的代码)。完成AOP编程。
1
MVC 在配置文件里,写了一个UrlRoutingModule,创建这个方法,在这个方法里的Init方法里,向管道事件的第七个事件注册了一个方法。这个方法主要做的是将MVCHandler添加到上下文中(HttpContext).【下面这个图是从浏览器请求开始的】
那么要研究MVC就从这个UrlRoutingModule(继承IHttpModule接口)方法开始研究。
2
UrlRoutingModule类下的Init()方法在第七个事件下注册了一个方法:
这个方法里:
1、 拿到HttpApplication对象,
2、 将上下文对象HttpContext封装到HttpContextBase里面。
3、 传入上下文对象,执行事件。
---------------------------------------------------------分割线------------------------------------------------------
3
1、 拿取路由数据。
4
1.1根据上下文,进行过滤,判断请求的是不是一个已经存在的文件,如果是,则直接返回这个文件。
1.2如果请求的不是存在的文件,那么获取路由数据。
获取路由数据的时候,调用的是RouteBase类下面的GetRouteData(httpContext)方法。
1.2.1RouteBase下的GetRouteData方法,但是,实现这个方法的类是Route。
继续看GetRouteData()方法:
因为在Reflector下不能写注释,我转到了MVC源码下面。
到这里,是时候说明一下那个RouteHandler是哪里来的了。
其实它就是MVCRouteHandler。我们到Global文件下去看。
5
A:这里注册路由,调用MvcApplication下的RegisterRoutes方法。即B
B:将路由信息传入到MapRoute下面,它其实就是返回一个Route对象回来。具体做了什么呢?
上面我在1.2.2那里标记了一下,那个就是Route类的一个构造函数
Route(string url,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对象里
RouteData data=new RouteData(this,andler).但是在里面做了一些检查,检查路径,检查约束。最后返回这个data。
还是看一下RouteData里面的内容吧:
6
这里面包含了MvcRouteHandler(RouteHandler),命名空间(dataTokens),路由数据?没去研究RouteValueDictionary()。反正这里包含了我们传进来的路由信息。保存在RouteCollection集合里面。提一下:RouteTable里也一个RouteCollection,静态的,是为了能够在整个生命周期里面使用到路由数据。如下图:
接着我们继续看第二部分吧。
2、 在第一部分里,已经将MvcRouteHandler添加到了routeData里面,返回一个data对象。而MvcRouteHandler最后传递为RouteHandler。
第二部分:IRouteHandlerrouteHandler = andler;从routeData里面获取到routeHandler对象。为什么是IRouteHandler类型呢?擦,因为从Route构造函数开始就是IRouteHandler类型定义来接收的····
接着看第三部分
3、 RequestContextrequestContext = new RequestContext(context, routeData);
tContext = requestContext;
将context对象和上面拿到的路由数据routeData封装到RequestContext里面,然后赋值给HttpContextBase下的HttpRequestBase的requestContext属性。也就是将路由数据和封装过的上下文信息再添加到上下文里面。
IHttpHandlerhttpHandler = pHandler(requestContext);
GetHttpHandler(requestContext) 这里返回一个MvcHandler。
7
然后我们去MvcHandler下去看看,还是不看先,留到后面看吧。应该就是调用PR方法执行后面一系列流程了。留待后面揭秘。暂时知道GetHttpHandler方法里返回这个MvcHandler对象就行了。接收类型是IhttpHandler接口!!!!!!!!!熟悉啦~~
接着看第四部分,也是在第七个事件里注册的方法执行的最后一步。
andler(httpHandler);
这个方法是把获得的那个MvcHandler添加到上下文对象中。这个方法具体做啥先。
先得说一下,在第三部分的时候,已经将context传进了HttpContextBase里。
待会用到HttpContextWrapper,它继承HttpContextBase,重写了HttpContextBase里面的ReMapHandler方法。。。。详细见图:
好了,进入ReMapHandler方法:
Typetype = e();//获得类型:MvcHandler
handlerType = lyQualifiedName;//获得当前类型在程序集里面的名字:dler
handlerName = me;//获得全名
this._remapHandler = handler;//将MvcHandler添加到上下文对象中,这里的this就是HttpContext
在第七个事件里注册的方法,最终就是拿到路由数据,将创建的Handler添加到上下文中。
PostResolveRequestCache(HttpContextBase context)到此,运行完···接着深入。
8
在原来的 的整个运行周期上,挑中合适的时机,弄出分叉来,然后诞生了。
那么这个时机在哪里呢?
1、 FrameWork 4.0下会先读取系统配置文件,这个文件下的节点HttpModules里配置了一个UrlRoutingModule,在读取这个配置文件的时候,就会创建这个Module对象,创建方法,在初始化的时候在第七个事件PostResolveRequestCache里注册方法,这个方法里面封装上下文和路由信息,创建了MvcHandler并添加到上了下文里(HttpContex)。
2、 在第八个事件(PostMapRequestHandler)执行时(是不是在执行的时候检查呢?还是在执行之前检查?这个还没有考证!),会先判断上面的那个_remapHandler是不是空的,如果不空(MVC执行程序),就不再创建页面类对象,直接返回Handler。否则根据请求路径创建页面类对象······等执行运行机制。
以上两个时机造就了MVC。在创建的MvcHandler里有我们最常见的PR(ProcessRequest)方法.
现在开始揭秘MvcHandler到底干了什么。(只研究主要的)
在整个运行的管道第九个事件里要拿到请求的Session,会检查当前请求的类是否实现了IRequiresSessionState接口。再看MvcHandler类,
它已经实现了这个接口!其实,这个MvcHandler就相当于是一个页面类对象。可以自己去该类下面看看。
跟一样,在第十一和十二个事件之间会调用页面类对象的PR方法,里调用page(继承自IHttpHandler)类的PR(是实现IHttpHandler的)方法。在里则调用MvcHandler(也继承自IHttpHandler)里的PR(也是实现IHttpHandler的)方法。
9
老样子,进入PR方法:
1、创建一个控制器接口对象,在初始化的时候为其赋值。创建控制器!根据拿到的控制器的类型,创建的行为是由工厂完成的!工厂在这里起到的作用除了提供多态外,还提供一个对象池,每一次创建控制器的时候都会到这个池里面去检查。
在ProcessRequestInit()方法里面:
接着走下去,看CreateController()方法。不做太多的解释了,到Create()方法,再到Activitor下的CreateInstance方法。反正最终就是根据type创建出这个实例。见下面两个图:
10
2、执行Execute()方法,这是一个很关键的方法。
11
在Initialize方法里:(this就是ControllerBase)
主要看ExecuteCore()方法:
好啦,走到这里终于到了调用Action了。在Action里面会存在一些与视图相关的东西。因此在action里面要创建视图(View()方法),设置数据,返回ViewResult···
从读取配置文件
在第七个事件里注册方法,创建MvcHandler,将路由信息和请求上下文信息传进去
MvcHandler为类页面类对象,调用里面的PR方法,通过反射创建controller对象,调用里面的Action。
Action就是我们平时直接写代码的方法。返回一个ActionResult return View();
So
接下来研究Action,是怎么创建视图返回的,又是怎样设置保存后台数据等等···
12
1、 执行程序员的action方法,返回ActionResult:
ViewResult就是。
这些数据保存到HomeController的父类的父类ControllerBase里面,然后再在Controller类里面new了一个ViewResult,执行action的时候就返回这个ViewResult,将这些数据传递保存到ViewResultBase里面,以供创建视图的时候使用!
2、 拿到ViewResult并保存到AuthContext里面(),开始执行ExecuteResult()方法!
13
1、 FindView(context):
1.1
1.1.1
1.1.1.1
14
找RazorViewEngine:
最终找到了FindView啦····
在FindView返回关联本地视图的引擎(啥?不懂),有母版页的时候的!
或者创建一个新的视图引擎····CreateView()
在RazorViewEngine下面找到了CreateView()
So
拿到了视图引擎了,Public IView View{set;get;} 已经赋值,
那么在Render()方法里面生成Html代码,并放入Response里····哈,整一条路线终于清晰啦。MVC整个机制就到这里·····
15
版权声明:本文标题:ASP.NET-MVC整体运行原理,走源码 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1705141323h474419.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论