MVC系统学习1—MVC执行流程
用MVC来做开发也有一段时间了,但是感觉一直没入门,就徘徊在似懂非懂的层次,和去年刚毕业学习WebForm时一样,当时通过张子阳老兄的几篇文章,明白了请求处理流程,页面生命周期才真正明白了WebForm的强大。由于MVC的学习资料比较少,牛人的技术博客也只是讲一些基础的而已。因此决定通过Asp.Net MVC源码来学习,由于是开源的,也不用Reflector作为辅助工具。首先还是明白下MVC的请求处理流程。有参考了MSDN上面的文章(http://msdn.microsoft.com/zh-cn/library/dd381612.aspx)
当应用程序第一次接受请求的时候,在Global.asax文件中,Route对象会添加到RouteTable对象中。RegisterRoutes函数就是我们实现的路由注册函数。
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RegisterRoutes(RouteTable.Routes); }<br> public static void RegisterRoutes(RouteCollection routes)<br> {<br> routes.IgnoreRoute("{resource}.axd/{*pathInfo}");<br><br> routes.MapRoute(<br> "Default",<br> "{controller}/{action}/{id}", <br> new { controller = "Home", action = "Index", id = UrlParameter.Optional } <br> );<br> }<br> |
通过MVC源码在了解上面这一步的大致实现过程 。在RegisterRoutes函数中,通过调用MapRoute(扩展方法)来实现向RouteCollection添加Route对象。最后调用的是下面的方法。
可以发现上面的方法实现创建一个Route对像,并将其添加到RouteCollection,然后将其返回。接下来了解下Route类。Route继承自RouteBase类.其有几个比较重要的属性。

上面这前三个成员的类型是RouteValueDictionary,而上面的函数中,是调用下面的这个函数来实现向Route的Defaults等添加数据。如注释,就是将controller,action,id添加到Defaults的键中,而将Home,Index加入到相应的键对应的值。而对于RouteHandler的作用等下再讲。这样就完成了一个Route对象的创建并且添加到RouteCollection中,而这个RouteCollection也就是RouteTable的成员Routes.
private void AddValues(object values) { if (values != null) { //这里分解出 new { controller = "Home", action = "Index", id = UrlParameter.Optional } //然后填充到字典里面 foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(values)) { object obj2 = descriptor.GetValue(values); this.Add(descriptor.Name, obj2); } } } |
在Asp.Net管道中执行MVC请求的HttpModule是UrlRoutingModule模块。UrlRoutingModule使用RouteTable 集合中第一个匹配的 Route 对象来创建 RouteData 对象,然后使用所创建的对象创建 RequestContext 对象。UrlRoutingModule里面有一个RouteCollection属性,其就是通过RouteTable.Routes来实现赋值的。
public System.Web.Routing.RouteCollection RouteCollection { get { //TODO:使用RouteTable的Routes成员来初始化routeCollection if (this._routeCollection == null) { this._routeCollection = RouteTable.Routes; } return this._routeCollection; } set { this._routeCollection = value; } } |
在UrlRoutingModule中,注册了两个HttpApplication公开的事件。其中是在OnApplicationPostResolveRequestCache方法里面实现路由匹配,因为其里面又调用了一个this.PostResolveRequestCache(context)方法,而在这个方法里面的第一句就是 RouteData routeData = this.RouteCollection.GetRouteData(context)。根据请求上下文来获取RouteData。路由匹配的奥秘貌似就在这里。
protected virtual void Init(HttpApplication application) { application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache); application.PostMapRequestHandler += new EventHandler(this.OnApplicationPostMapRequestHandler); } |
this.RouteCollection.GetRouteData(context)方法里面最后又这么几句代码。通过遍历当前的RouteCollection来实现RouteData的获取,如果获取到则立即返回。这里其实遍历的单个对象不是RouteBase而是Route,而Route继承自RouteBase类,并且重写了RouteBase的抽象函数GetRouteData(为什么这么做,待研究?)。而路由匹配的实现也是在Route类里重写的GetRouteData方法。
foreach (RouteBase base2 in this) { RouteData routeData = base2.GetRouteData(httpContext); if (routeData != null) { return routeData; } } |
Route的GetRouteData方法
public override RouteData GetRouteData(HttpContextBase httpContext)
{
//获取请求的虚拟路径
string virtualPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring() + httpContext.Request.PathInfo;
//TODO:接下来进行路径的匹配
RouteValueDictionary values = this._parsedRoute.Match(virtualPath, this.Defaults);
if (values == null)
{
return null;
}
RouteData data = new RouteData(this, this.RouteHandler);
//如果不通过约束则返回空
if (!this.ProcessConstraints(httpContext, values, RouteDirection.IncomingRequest))
{
return null;
}
foreach (KeyValuePair<string, object> pair in values)
{
data.Values.Add(pair.Key, pair.Value);
}
if (this.DataTokens != null)
{
foreach (KeyValuePair<string, object> pair2 in this.DataTokens)
{
data.DataTokens[pair2.Key] = pair2.Value;
}
}
return data;
}
最后是在这个方法下面调用ParsedRoute的Match进行路由匹配
MVC系统学习1—MVC执行流程的更多相关文章
- MVC系统学习2—MVC路由
在MVC下不是通过对物理文件的映射来实行访问的,而是通过定义后的路由Url来实现访问的.在前一篇讲到我们是在全局文件下进行路由配置. routes.MapRoute( & ...
- Spring 框架基础(06):Mvc架构模式简介,执行流程详解
本文源码:GitHub·点这里 || GitEE·点这里 一.SpringMvc框架简介 1.Mvc设计理念 MVC是一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码,将业务逻辑聚集 ...
- 大数据学习day23-----spark06--------1. Spark执行流程(知识补充:RDD的依赖关系)2. Repartition和coalesce算子的区别 3.触发多次actions时,速度不一样 4. RDD的深入理解(错误例子,RDD数据是如何获取的)5 购物的相关计算
1. Spark执行流程 知识补充:RDD的依赖关系 RDD的依赖关系分为两类:窄依赖(Narrow Dependency)和宽依赖(Shuffle Dependency) (1)窄依赖 窄依赖指的是 ...
- python学习之内部执行流程,内部执行流程,编码(一)
python的执行流程: 加载内存--->词法分析--->语法分析--->编译--->转换字节码---->转换成机器码---->供给CPU调度 python的编码: ...
- MVC系统学习6—Filter
Mvc的过滤器是特性类,可以使我们在执行Action之前,执行Action之后,执行Action发生异常时,编写相关的处理代码实现某些逻辑.下面是四个基本的Filter接口. 上面这四个基本的Filt ...
- MVC系统学习5——验证
其实关于Mvc的验证在上一篇已经有讲过一些了,可以通过在我们定义的Model上面添加相应的System.ComponentModel.DataAnnotations空间下的验证属性.在服务器端通过Mo ...
- MVC系统学习3—ModelBinder
在ASP.NET MVC中,每个请求都被映射到一个Action方法,我们可以在action的方法中定义相应类型的参数,View中通过post.get方式提交的request参数,只要名称一致就会对应到 ...
- Mvc系统学习9——Areas学习
在Mvc2.0中,新增加了一个特性就是Areas.在没有有使用Areas的情况下,我们的Mvc项目组织是下面这样的.当项目庞大的时候,Controllers,Model,View文件下下面势必会有很多 ...
- MVC系统学习7—Action的选择过程
在Mvc源码的ControllerActionInvoker的InvokeAction方法里面有一个FindAction方法,FindAction方法在ControllerDescriptor里面定义 ...
随机推荐
- js滚轮事件需要注意的兼容性问题
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Python基础 — Pandas
Pandas -- 简介 Python Data Analysis Library 或 pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的. Pandas ...
- 清北考前刷题day1早安
立方数(cubic) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK定义了一个数叫“立方数”,若一个数可以被写作是一个正整数的3次方,则这个数就是立方数 ...
- deepin 安装 idea
1.su root 2.sudo apt install idea 3.sudo vi /etc/hosts 最后一行添加 0.0.0.0 account.jetbrains.com 4.注册码 N7 ...
- LOJ#557. 「Antileaf's Round」你这衣服租来的吗(FHQ Treap+珂朵莉树)
题面 传送门 题解 好吧我是不太会复杂度分析-- 我们对于每种颜色用一个数据结构维护(比方说线段树或者平衡树,代码里写的平衡树),那么区间询问很容易就可以解决了 所以现在的问题是区间修改,如果区间颜色 ...
- python自动化测试学习笔记-9测试框架
学习了这么久的python,我们已经可以自己搭建一个简单的测试和框架了,先从简单的开始,有时我们编写接口的测试用例会用excel进行编写,以下面的接口测试用例模板为例,进行编写:
- 递推DP HDOJ 5375 Gray code
题目传送门 /* 题意:给一个串,只能是0,1,?(0/1).计算格雷码方法:当前值与前一个值异或,若为1,可以累加a[i],问最大累加值 DP:dp[i][0/1]表示当前第i位选择0/1时的最大分 ...
- Javascript 排序算法(转)
1.快速排序 class QuickSort { Sort(originalArray) { // 复制 originalArray 数组防止它被修改 const array = [...origin ...
- 1102 A-B数对
题目描述 出题是一件痛苦的事情! 题目看多了也有审美疲劳,于是我舍弃了大家所熟悉的A+B Problem,改用A-B了哈哈! 好吧,题目是这样的:给出一串数以及一个数字C,要求计算出所有A-B=C的数 ...
- Spring框架系列(四)--IOC控制反转和DI依赖注入
背景: 如果对象的引用或者依赖关系的管理由具体对象完成,代码的耦合性就会很高,代码测试也变得困难.而IOC可以很好的解决这个问题,把这 些依赖关系交给框架或者IOC容器进行管理,简化了开发. IOC是 ...