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

推荐订阅源

量子位
Stack Overflow Blog
Stack Overflow Blog
人人都是产品经理
人人都是产品经理
The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
Vercel News
Vercel News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Y
Y Combinator Blog
The Cloudflare Blog
Last Week in AI
Last Week in AI
B
Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tailwind CSS Blog
V
Visual Studio Blog
博客园 - 三生石上(FineUI控件)
小众软件
小众软件
Google DeepMind News
Google DeepMind News
D
DataBreaches.Net
博客园 - 司徒正美
B
Blog RSS Feed
Microsoft Azure Blog
Microsoft Azure Blog
罗磊的独立博客
Hugging Face - Blog
Hugging Face - Blog
L
LangChain 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

查看大图