<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      代碼改變世界

      MVC之前的那點事兒系列(9):MVC如何在Pipeline中接管請求的?

      2014-06-10 09:13  湯姆大叔  閱讀(4730)  評論(12)    收藏  舉報

      文章內(nèi)容

      上個章節(jié)我們講到了,可以在HttpModules初始化之前動態(tài)添加Route的方式來自定義自己的HttpHandler,最終接管請求的,那MVC是這么實現(xiàn)的么?本章節(jié)我們就來分析一下相關(guān)的MVC源碼來驗證一下我們的這個問題。

      先創(chuàng)建一個MVC3的Web Application,選擇默認的模板以便創(chuàng)建以后就默認包含HomeController和AccountController。我們知道MVC要先接管請求才能通過這些Controller來處理,那我們先去Global.asax.cs文件里看代碼(定義接管請求要在初始化HttpModule之前,所以只能到這里來找代碼(或者是利用WebActivator之類的特性來動態(tài)添加),Global.asax.cs文件里代碼很少,但是有我們需要的東西,首先在Application_Start的方法里發(fā)現(xiàn)一行代碼:

      RegisterRoutes(RouteTable.Routes);

      這行代碼,看調(diào)用的方法名稱RegisterRoutes是注冊Route的意思,但是為什么參數(shù)卻是全局的RouteTable.Routes集合呢?找到RegisterRoutes方法來看看具體的內(nèi)容:

      public static void RegisterRoutes(RouteCollection routes)
      {
          routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
      
          routes.MapRoute(
              "Default", // Route name
              "{controller}/{action}/{id}", // URL with parameters
              new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
          );
      }

      該方法有2行代碼,第一行是忽略一個Route(我們先不看這個),第二行是使用MapRoute方法注冊一個新的Route,默認是映射到Home Controller的Index Action上,我們可能想到了,RouteCollection(也就是剛才傳入的RouteTable.Routes)的MapRoute方法就是提供我們所說的接管請求的入口,但是如何把MVC自己的HttpHandler傳進去的呢?我們Go to一下這個MapRoute方法(需要安裝ReShaper來查找MVC的源碼),調(diào)整到了MVC的RouteCollectionExtensions類,發(fā)現(xiàn)MapRoute并不是RouteCollection自帶的方法,而是在MVC源碼里提供的一個擴展方法,代碼如下:

      public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces)
      {
          if (routes == null)
          {
              throw new ArgumentNullException("routes");
          }
          if (url == null)
          {
              throw new ArgumentNullException("url");
          }
      
          Route route = new Route(url, new MvcRouteHandler())
          {
              Defaults = new RouteValueDictionary(defaults),
              Constraints = new RouteValueDictionary(constraints),
              DataTokens = new RouteValueDictionary()
          };
      
          if ((namespaces != null) && (namespaces.Length > 0))
          {
              route.DataTokens["Namespaces"] = namespaces;
          }
      
          routes.Add(name, route);
      
          return route;
      }

      該代碼的主要作用是new一個新的Route,然后將該Route添加到我們剛才提到的靜態(tài)集合RouteTable.Routes里,以便后期查找Handler的時候使用,OK,這一步符合我們前面章節(jié)的分析。

      接下來看,Route是如何new出來的,代碼里的參數(shù)傳入的分別是我們知道的url,以及一個MVCRouteHandler的實例,這一步也符合我們前面的分析,那我們來看一下MVCRouteHandler的GetHttpHandler方法是如何實現(xiàn)的獲取MVCHandler的:

          public class MvcRouteHandler : IRouteHandler { 
              private IControllerFactory _controllerFactory;
       
              public MvcRouteHandler() { 
              }
       
              public MvcRouteHandler(IControllerFactory controllerFactory) {
                  _controllerFactory = controllerFactory;
              }
       
              protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext) {
                  requestContext.HttpContext.SetSessionStateBehavior(GetSessionStateBehavior(requestContext)); 
                  return new MvcHandler(requestContext); 
              }
       
              protected virtual SessionStateBehavior GetSessionStateBehavior(RequestContext requestContext) {
                  string controllerName = (string)requestContext.RouteData.Values["controller"];
                  IControllerFactory controllerFactory = _controllerFactory ?? ControllerBuilder.Current.GetControllerFactory();
                  return controllerFactory.GetControllerSessionBehavior(requestContext, controllerName); 
              }
       
              #region IRouteHandler Members 
              IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext) {
                  return GetHttpHandler(requestContext); 
              }
              #endregion
          }

      看以上的粗體代碼,MvcRouteHandler在實現(xiàn)了IRouteHandler的GetHttpHandler,該方法調(diào)用了MvcRouteHandler自身定義的GetHttpHandler虛方法,而在這個虛方法里我們看到了一個非常重要而又期待已久的代碼——返回MvcHandler的實例,大概看一下MvcHandler這個類,得到它就是我們所猜想的:繼承于IHttpHandler接口的一個類,并且也繼承了 IHttpAsyncHandler接口,我們先不管MvcHandler內(nèi)部是如何實現(xiàn)的,但我們前面幾章節(jié)的全部分析終于得到了驗證,也就說在這里得到了Mvc的專用處理Handler,然后調(diào)用它的BeginProcessRequest方法進入Mvc自身的Pipeline進行處理了。

       

      至此,我們終于弄明白了Mvc在整個ASP.NET Runtime是如何接管請求的了,也應(yīng)該大概清楚整個ASP.NET Runtime的運行機制了,至于MvcHandler的實現(xiàn)方式,我們會在后面的很多章節(jié)逐一給大家分析每行代碼,今天我們還有一個小任務(wù),那就是:看完了Mvc的實現(xiàn)機制,我們能否自己來寫一個自定義的HttpHandler通過Route動態(tài)注冊進去,來實現(xiàn)我們自己的自定義擴展,我們來嘗試著做一下吧。

      第一步:建立HttpHandler類

          public class TomHandler : IHttpHandler
          {
              public TomHandler(RequestContext requestContext)
              {
                  // do nothing
              }
      
              public virtual void ProcessRequest(HttpContext context)
              {
                  string url = context.Request.Url.AbsoluteUri;
                  context.Response.Write("當(dāng)前地址為:" + url);
                  context.Response.End();
                  // 這里我們什么都不做,只輸出URL地址
              }
      
              public virtual bool IsReusable
              {
                  get
                  {
                      return false;
                  }
              }
          }

      第二步:建立RouteHandler類

      public class TomRouteHandler : IRouteHandler
      {
          IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)
          {
              return new TomHandler(requestContext);
          }
      }

      在GetHttpHandler實現(xiàn)里,返回我們定義的TomHandler實例。

       

      第三步:注冊我們的Route和RouteHandler

      protected void Application_Start(object sender, EventArgs e)
      {
          Route route = new Route("tom/{other}", new TomRouteHandler());
          RouteTable.Routes.Add(route);
      }

       

      我們設(shè)置成,只要訪問tom文件夾下的任意文件或者子目錄,都提示該URL。下面是我的測試結(jié)果:

      訪問:Http//localhost/tom/

      結(jié)果:沒有提示我們預(yù)想的結(jié)果(原因是不符合我們的規(guī)則)

      訪問:Http//localhost/tom/123/

      結(jié)果:輸出正常(說明TomHandler已經(jīng)接管了該請求)

      訪問:Http//localhost/tom/123.aspx?id=123

      結(jié)果:輸出正常(也說明TomHandler已經(jīng)接管了該請求)

       

      在建立真實的tom文件夾,然后在里面建立一個 index.html文件(內(nèi)容為123),然后訪問Http//localhost/tom/index.html,規(guī)則符合我們的Route定義,但輸出結(jié)果卻不是我們預(yù)期的結(jié)果,而是123,怎么回事?還記得上一章節(jié)里談到的RouteCollection的GetRouteData方法么?該方法是先判斷URL對應(yīng)的文件是否真實存在,如果存在就直接輸出,如果不存在就再來找RouteData的數(shù)據(jù),這就解釋了上面的index.html路徑為什么不是我們期望結(jié)果的原因了吧?。

       

      注:如果你建立一個index.aspx文件,并在index.aspx.cs文件里寫Response.Write代碼輸出123的話,該文件也會按照aspx頁面的正常周期來執(zhí)行(也就是說輸出123字符串),如果你在<system.web>里的httpHandlers節(jié)點用remove命令把*.aspx的匹配設(shè)置去掉,那結(jié)果就只會輸出index.aspx這個文件里的字符串了(包括里面內(nèi)嵌的任何C#代碼)。

       

      最后總結(jié)了,到這里,我們已經(jīng)知道了MvcHandler是如何接管請求的了,而且自己也做了一個簡單的例子來驗證這套機制。重新回顧一下前面的這么多篇文章,我們應(yīng)該大概對ASP.NET RunTime, Pipeline以及ASP.NET MVC切入點應(yīng)該有個整體的了解了。

      同步與推薦

      本文已同步至目錄索引:MVC之前的那點事兒系列

      MVC之前的那點事兒系列文章,包括了原創(chuàng),翻譯,轉(zhuǎn)載等各類型的文章,如果對你有用,請推薦支持一把,給大叔寫作的動力。

      主站蜘蛛池模板: 国产在线观看黄| 亚洲色欲在线播放一区二区三区| 国产精品国语对白一区二区| 儋州市| 日韩精品成人一区二区三| 亚洲人成小说网站色在线| 92精品国产自产在线观看481页| 国产熟睡乱子伦午夜视频| 精品国产乱码久久久久夜深人妻 | 国产成人精品亚洲高清在线| 亚洲精品电影院| 国产亚洲欧洲av综合一区二区三区| 宜城市| 99久久精品国产一区二区蜜芽| 国产黄色一区二区三区四区| 在线视频中文字幕二区| 亚洲精品欧美综合二区| 国产精品夜夜春夜夜爽久久小| 亚洲大尺度一区二区av| 日韩有码中文字幕国产| 亚洲精品人成网线在播放VA| 亚洲欧美国产精品久久久久久久| 久久亚洲av成人无码软件| 伊人色综合久久天天| 久久人与动人物a级毛片| 国产中文字幕日韩精品| 欧美三级欧美成人高清| 精品国产成人A区在线观看| 欧美寡妇xxxx黑人猛交| 西乌| 国产熟女肥臀精品国产馆乱| 亚洲欧美中文日韩在线v日本| 国产九九视频一区二区三区| 欧美高清狂热视频60一70| 国产精品午夜福利精品| 国产91色综合久久高清| 欧美人禽杂交狂配| 无码h黄肉动漫在线观看| 亚洲中文一区二区av| 日韩大尺度一区二区三区| 国产资源精品中文字幕|