惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 三生石上(FineUI控件)
S
SegmentFault 最新的问题
阮一峰的网络日志
阮一峰的网络日志
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
雷峰网
雷峰网
Apple Machine Learning Research
Apple Machine Learning Research
WordPress大学
WordPress大学
博客园 - 司徒正美
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
宝玉的分享
宝玉的分享
爱范儿
爱范儿
月光博客
月光博客
The GitHub Blog
The GitHub Blog
M
MIT News - Artificial intelligence
H
Hackread – Cybersecurity News, Data Breaches, AI and More
B
Blog
T
Tailwind CSS Blog
美团技术团队
D
Docker
V
Visual Studio Blog
Martin Fowler
Martin Fowler
博客园 - 聂微东
The Cloudflare Blog

博客园 - Jacky_Xu

推荐--jQuery使用手册 一种理想的在关系数据库中存储树型结构数据的方法 资料收集:高并发 高性能 高扩展性 Web 2.0 站点架构设计及优化策略 Windows Communication Foundation入门 网页加速系列 用VS.NET中的测试工具测试ASP.NET程序 【转载】优化ASP.NET应用程序性能研究与探讨 负载均衡技术全攻略 Windows 2003系统负载平衡策略全攻略 【经典】高并发高流量网站架构 C# Delegate 简介 .NET牛人应该知道些什么 让你成为有钱人的25种方法! MSDN 杂志 asp.net ajax 文章汇集 网站设计者:提高网页打开速度的一些小技巧 jquery技巧总结 ASP.NET MVC Preview 2 - 流程分析 (3) ASP.NET MVC Preview 2 - 流程分析 (2) Blogger必修:10个能用JavaScript实现的图片特效
ASP.NET MVC Preview 2 - 流程分析 (1) - Jacky_Xu
Jacky_Xu · 2008-04-30 · via 博客园 - Jacky_Xu

2008-04-30 13:17  Jacky_Xu  阅读(533)  评论()    收藏  举报

很早就想写来着,尤其是用 MVC Preview 1 做过一个项目以后。不过,依照微软以往的习惯,Beta2 之前的每个版本之间都有很大的差异,本文有多少生命周期,也很难说。不废话,开始正文……

MVC 通过在 web.config 中添加相应的 Module 来参与 ASP.NET 执行流程。

<httpModules>
  <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing ..." />
</httpModules>

那么,这个 UrlRoutingModule 自然就是我们分析过程的入口。

public class UrlRoutingModule : IHttpModule
{
  protected virtual void Init(HttpApplication application)
  {
    application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);
    application.PostMapRequestHandler += new EventHandler(this.OnApplicationPostMapRequestHandler);
  }  
}

订阅了两个 HttpApplication 事件~~~~ 嗯,PostResolveRequestCache 要比 PostMapRequestHandler 更早执行,先从它开始吧。

private void OnApplicationPostResolveRequestCache(object sender, EventArgs e)
{
  HttpContextBase context = new HttpContextWrapper2(((HttpApplication) sender).Context);
  this.PostResolveRequestCache(context);
}

public virtual void PostResolveRequestCache(HttpContextBase context)
{
  RouteData routeData = this.RouteCollection.GetRouteData(context);
  if (routeData != null)
  {
    IRouteHandler routeHandler = routeData.RouteHandler;
    if (routeHandler == null)
    {
      throw new InvalidOperationException(...);
    }

    RequestContext requestContext = new RequestContext(context, routeData);
    IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
    if (httpHandler == null)
    {
      throw new InvalidOperationException(...);
    }

    context.Items[_requestDataKey] = new RequestData { OriginalPath = context.Request.Path, HttpHandler = httpHandler };
    context.RewritePath("~/UrlRouting.axd");
  }
}

首先从 RouteCollection 中获取一个 RouteData 对象,RouteCollection 何许人也?

public RouteCollection RouteCollection
{
  get
  {
    if (this._routeCollection == null)
    {
      this._routeCollection = RouteTable.Routes;
    }
    return this._routeCollection;
  }
  set
  {
    this._routeCollection = value;
  }
}

说白了,所谓 RouteCollection 就是我们在 Global.asax.cs 中添加的 Route 集合。

public static void RegisterRoutes(RouteCollection routes)
{
  // Note: Change the URL to "{controller}.mvc/{action}/{id}" to enable
  // automatic support on IIS6 and IIS7 classic mode

  routes.Add(new Route("{controller}/{action}/{id}", new MvcRouteHandler())
  {
    Defaults = new RouteValueDictionary(new { action = "Index", id = "" }),
  });

  routes.Add(new Route("Default.aspx", new MvcRouteHandler())
  {
    Defaults = new RouteValueDictionary(new { controller = "Home", action = "Index", id = "" }),
  });
}

回到上文,在获取 RoteCollection 之后,通过调用 GetRouteData(context) 返回一个 RouteData 对象(详细代码可阅读 Route.GetRouteData 方法,它通过分析当前上下文的相关请求参数,返回所需的结果对象),该对象内部包含了我们注册 Route 时的相关设置,当然就有下面所需要的 —— MvcRouteHandler。

接下来,该方法将 routeData 和上下文一起打包成 RequestContext,这应该是给后面相关处理准备的上下文环境。通过调用 MvcRouteHandler.GetHttpHandler() 方法,我们终于看到了曙光,也就是进行后续流程的关键 —— MvcHandler (有关 MvcHandler 的细节,后续章节再说)。

public class MvcRouteHandler : IRouteHandler
{
  protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext)
  {
    return new MvcHandler(requestContext);
  }
}

到了这一步,MVC 框架已经准备好了相应的执行场景,接下来就是修改默认的执行流程了。当然,辛苦得来的 "环境" 要选择一个合适的 "人",存储到一个合适的 "地方"。

context.Items[_requestDataKey] = new RequestData { OriginalPath = context.Request.Path, HttpHandler = httpHandler };

而后的某个时间,OnApplicationPostMapRequestHandler 被执行。在 PostMapRequestHandler 中,它提取了前面预先 "埋" 下的 "坏蛋",并修改了 HttpContext.Handler,使得 MvcHandler 能继续未完的 "事业"。至于跳转之类的,就无需我再多说。

private void OnApplicationPostMapRequestHandler(object sender, EventArgs e)
{
  HttpContextBase context = new HttpContextWrapper2(((HttpApplication) sender).Context);
  this.PostMapRequestHandler(context);
}

public virtual void PostMapRequestHandler(HttpContextBase context)
{
  RequestData data = (RequestData) context.Items[_requestDataKey];
  if (data != null)
  {
    context.RewritePath(data.OriginalPath);
    context.Handler = data.HttpHandler;
  }
}

待续……

----------------------------

附上流程分析图

uploads/200803/11_155627_mvc1.png

查看大图