自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

詳解ASP.NET MVC的請(qǐng)求生命周期

開(kāi)發(fā) 后端
本文的目的是描述ASP.NET MVC請(qǐng)求從開(kāi)始到結(jié)束的整個(gè)生命周期。主要研究了處理ASP.NET MVC請(qǐng)求的5個(gè)過(guò)程:創(chuàng)建RouteTable、UrlRoutingModule攔截請(qǐng)求、生成控制器、執(zhí)行行為以及呈現(xiàn)視圖。最后介紹了ASP.NET MVC框架的可擴(kuò)展點(diǎn)。

本文的目的旨在詳細(xì)描述ASP.NET MVC請(qǐng)求從開(kāi)始到結(jié)束的每一個(gè)過(guò)程。我希望能理解在瀏覽器輸入U(xiǎn)RL并敲擊回車(chē)來(lái)請(qǐng)求一個(gè)ASP.NET MVC網(wǎng)站的頁(yè)面之后發(fā)生的任何事情。

為什么需要關(guān)心這些?有兩個(gè)原因。首先是因?yàn)锳SP.NET MVC是一個(gè)擴(kuò)展性非常強(qiáng)的框架。例如,我們可以插入不同的ViewEngine來(lái)控制網(wǎng)站內(nèi)容呈現(xiàn)的方式。我們還可以定義控制器生成和分配到某個(gè)請(qǐng)求的方式。因?yàn)槲蚁氚l(fā)掘任何ASP.NET MVC頁(yè)面請(qǐng)求的擴(kuò)展點(diǎn),所以我要來(lái)探究請(qǐng)求過(guò)程中的一些步驟。

其次,如果你對(duì)測(cè)試驅(qū)動(dòng)開(kāi)發(fā)佷感興趣,當(dāng)為控制器寫(xiě)單元測(cè)試時(shí),我們就必須理解控制器的依賴(lài)項(xiàng)。在寫(xiě)測(cè)試的時(shí)候,我們需要使用諸如Typemock Isolator或Rhino Mocks的Mock框架來(lái)模擬某些對(duì)象。如果不了解頁(yè)面請(qǐng)求生命周期就不能進(jìn)行有效的模擬。

生命周期步驟概覽

當(dāng)我們對(duì)ASP.NET MVC網(wǎng)站發(fā)出一個(gè)請(qǐng)求的時(shí)候,會(huì)發(fā)生5個(gè)主要步驟:

步驟1:創(chuàng)建RouteTable

當(dāng)ASP.NET應(yīng)用程序***次啟動(dòng)的時(shí)候才會(huì)發(fā)生***步。RouteTable把URL映射到Handler。

步驟2:UrlRoutingModule攔截請(qǐng)求

第二步在我們發(fā)起請(qǐng)求的時(shí)候發(fā)生。UrlRoutingModule攔截了每一個(gè)請(qǐng)求并且創(chuàng)建和執(zhí)行合適的Handler。

步驟3:執(zhí)行MvcHandler

MvcHandler創(chuàng)建了控制器,并且把控制器傳入ControllerContext,然后執(zhí)行控制器。

步驟4:執(zhí)行控制器

控制器檢測(cè)要執(zhí)行的控制器方法,構(gòu)建參數(shù)列表并且執(zhí)行方法。

步驟5:調(diào)用RenderView方法

大多數(shù)情況下,控制器方法調(diào)用RenderView()來(lái)把內(nèi)容呈現(xiàn)回瀏覽器。Controller.RenderView()方法把這個(gè)工作委托給某個(gè)ViewEngine來(lái)做。

現(xiàn)在讓我們來(lái)詳細(xì)研究每一個(gè)步驟:

步驟1:創(chuàng)建RouteTable

當(dāng)我們請(qǐng)求普通ASP.NET應(yīng)用程序頁(yè)面的時(shí)候,對(duì)于每一個(gè)頁(yè)面請(qǐng)求都會(huì)在磁盤(pán)上有這樣一個(gè)頁(yè)面。例如,如果我們請(qǐng)求一個(gè)叫做SomePage.aspx的頁(yè)面,在WEB服務(wù)器上就會(huì)有一個(gè)叫做SomePage.aspx的頁(yè)面。如果沒(méi)有的話(huà),會(huì)得到一個(gè)錯(cuò)誤。

從技術(shù)角度說(shuō),ASP.NET頁(yè)面代表一個(gè)類(lèi),并且不是普通類(lèi)。ASP.NET頁(yè)面是一個(gè)Handler。換句話(huà)說(shuō),ASP.NET頁(yè)面實(shí)現(xiàn)了IhttpHandler接口并且有一個(gè)ProcessRequest()方法用于在請(qǐng)求頁(yè)面的時(shí)候接受請(qǐng)求。ProcessRequest()方法負(fù)責(zé)生成內(nèi)容并把它發(fā)回瀏覽器。

因此,普通ASP.NET應(yīng)用程序的工作方式佷簡(jiǎn)單明了。我們請(qǐng)求頁(yè)面,頁(yè)面請(qǐng)求對(duì)應(yīng)磁盤(pán)上的某個(gè)頁(yè)面,這個(gè)頁(yè)面執(zhí)行ProcessRequest()方法并把內(nèi)容發(fā)回瀏覽器。

ASP.NET MVC應(yīng)用程序不是以這種方式工作的。當(dāng)我們請(qǐng)求一個(gè)ASP.NET MVC應(yīng)用程序的頁(yè)面時(shí),在磁盤(pán)上不存在對(duì)應(yīng)請(qǐng)求的頁(yè)面。而是,請(qǐng)求被路由轉(zhuǎn)到一個(gè)叫做控制器的類(lèi)上??刂破髫?fù)責(zé)生成內(nèi)容并把它發(fā)回瀏覽器。

當(dāng)我們寫(xiě)普通ASP.NET應(yīng)用程序的時(shí)候,會(huì)創(chuàng)建很多頁(yè)面。在URL和頁(yè)面之間總是一一對(duì)應(yīng)進(jìn)行映射。每一個(gè)頁(yè)面請(qǐng)求對(duì)應(yīng)相應(yīng)的頁(yè)面。

相反,當(dāng)我們創(chuàng)建ASP.NET MVC應(yīng)用程序的時(shí)候,創(chuàng)建的是一批控制器。使用控制器的優(yōu)勢(shì)是可以在URL和頁(yè)面之間可以有多對(duì)一的映射。例如,所有如下的URL都可以映射到相同的控制器上。

http://MySite/Products/1
http://MySite/Products/2
http://MySite/Products/3

這些URL映射到一個(gè)控制器上,通過(guò)從URL中提取產(chǎn)品ID來(lái)顯示正確的產(chǎn)品。這種控制器方式比傳統(tǒng)的ASP.NET方式更靈活??刂破鞣绞娇梢援a(chǎn)品更顯而易見(jiàn)的URL。

那么,某個(gè)頁(yè)面請(qǐng)求是怎么路由到某個(gè)控制器上的呢?ASP.NET MVC應(yīng)用程序有一個(gè)叫做路由表(Route Table)的東西。路由表映射某個(gè)URL到某個(gè)控制器上。

一個(gè)應(yīng)用程序有一個(gè)并且只會(huì)有一個(gè)路由表。路由表在Global.asax文件中創(chuàng)建。清單1包含了在使用Visual Studio新建ASP.NET MVC Web應(yīng)用程序時(shí)默認(rèn)的Global.asax文件。

清單 1 – Global.asax

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
 
namespace TestMVCArch
{
   public class GlobalApplication : System.Web.HttpApplication
   {
    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 = "" }),
     });
    }

    protected void Application_Start(object sender, EventArgs e)

 

    {

     RegisterRoutes(RouteTable.Routes);

    }

   }

  }

#p#

應(yīng)用程序的路由表由RouteTable.Routes的靜態(tài)屬性表示。這個(gè)屬性表示了路由對(duì)象的集合。在清單1列出的Global.asax文件中,我們?cè)趹?yīng)用程序***啟動(dòng)時(shí)為路由表增加兩個(gè)路由對(duì)象(Application_Start()方法在***次請(qǐng)求網(wǎng)站頁(yè)面的時(shí)候被調(diào)用一次)。

路由對(duì)象負(fù)責(zé)把URL映射到Handler。在清單1中,我們創(chuàng)建了兩個(gè)路由對(duì)象。這2個(gè)對(duì)象都把URL映射到MvcRouteHandler。***個(gè)路由映射任何符合{controller}/{action}/{id}模式的URL到MvcRouteHandler。第二個(gè)路由映射某個(gè)URL Default.aspx到MvcRouteHandler。

順便說(shuō)一下,這種新的路由構(gòu)架可以脫離ASP.NET MVC獨(dú)立使用。Global.asax文件映射URL到MvcRouteHandler。然而,我們可以選擇把URL路由到不同類(lèi)型的Handler上。這里說(shuō)的路由構(gòu)架包含在一個(gè)叫做System.Web.Routing.dll的獨(dú)立程序集中。我們可以脫離MVC使用路由。

步驟2:UrlRoutingModule攔截請(qǐng)求

當(dāng)我們對(duì)ASP.NET MVC應(yīng)用程序發(fā)起請(qǐng)求的時(shí)候,請(qǐng)求會(huì)被UrlRoutingModule HTTP Module攔截。HTTP Module是特殊類(lèi)型的類(lèi),它參與每一次頁(yè)面請(qǐng)求。例如,傳統(tǒng)ASP.NET包含了FormsAuthenticationModule HTTP Module用來(lái)使用表單驗(yàn)證實(shí)現(xiàn)頁(yè)面訪(fǎng)問(wèn)安全性。

UrlRoutingModule攔截請(qǐng)求后做的***件事情就是包裝當(dāng)前的HttpContext為HttpContextWrapper2對(duì)象。HttpContextWrapper2類(lèi)和派生自HttpContextBase的普通HttpContext類(lèi)不同。創(chuàng)建的HttpContext的包裝可以使使用諸如Typemock Isolator或Rhino Mocks的Mock對(duì)象框進(jìn)行模擬變得更簡(jiǎn)單。

接著,Module把包裝后的HttpContext傳給在之前步驟中創(chuàng)建的RouteTable。HttpContext包含了URL、表單參數(shù)、查詢(xún)字符串參數(shù)以及和當(dāng)前請(qǐng)求關(guān)聯(lián)的cookie。如果在當(dāng)前請(qǐng)求和路由表中的路由對(duì)象之間能找到匹配,就會(huì)返回路由對(duì)象。

如果UrlRoutingModule成功獲取了RouteData對(duì)象,Module然后就會(huì)創(chuàng)建表示當(dāng)前HttpContext和RouteData的RouteContext對(duì)象。Module然后實(shí)例化基于RouteTable的新HttpHandler,并且把RouteContext傳給Handler的構(gòu)造函數(shù)。

對(duì)于ASP.NET MVC應(yīng)用程序,從RouteTable返回的Handler總是MvcHandler(MvcRouteHandler返回MvcHandler)。只要UrlRoutingModule匹配當(dāng)前請(qǐng)求到路由表中的路由,就會(huì)實(shí)例化帶有當(dāng)前RouteContext的MvcHandler。

Module進(jìn)行的***一步就是把MvcHandler設(shè)置為當(dāng)前的HTPP Handler。ASP.NET應(yīng)用程序自動(dòng)調(diào)用當(dāng)前HTTP Handler的ProcessRequest()方法然后轉(zhuǎn)入下一步。

步驟3:執(zhí)行MvcHandler

在之前的步驟中,表示某個(gè)RouteContext的MvcHandler被設(shè)置作為當(dāng)前的HTTP Handler。ASP.NET應(yīng)用程總是會(huì)發(fā)起一系列的事件,包括Star、BeginRequest、PostResolveRequestCache、 PostMapRequestHandler、PreRequestHandlerExecute和EndRequest事件(非常多的應(yīng)用程序事件——對(duì)于完整列表,請(qǐng)查閱Visual Studio 2008文檔中的HttpApplication類(lèi))。

之前內(nèi)容中描述的所有東西都在PostResolveRequestCache和PostMapRequestHandler中發(fā)生。當(dāng)前HTTP Handler的ProcessRequest()方法在PreRequestHandlerExecute事件之后被調(diào)用。

當(dāng)之前內(nèi)容中創(chuàng)建的MvcHandler對(duì)象的ProcessRequest()被調(diào)用的時(shí)候,會(huì)創(chuàng)建一個(gè)新的控制器??刂破饔蒀ontrollerFactory創(chuàng)建。由于我們可以創(chuàng)建自己的ControllerFactory,所以這又是一個(gè)可擴(kuò)展點(diǎn)。默認(rèn)的ControllerFactory名字相當(dāng)合適,叫做DefaultControllerFactory。

RequestContext以及控制器的名字被傳入ControllerFactory.CreateController()方法來(lái)獲得一個(gè)控制器。然后,從RequestContext和控制器構(gòu)造ControllerContext對(duì)象。***,調(diào)用控制器類(lèi)的Execute()方法。在調(diào)用Execute()方法的時(shí)候會(huì)給方法傳入ControllerContext。

步驟4:執(zhí)行控制器

Execute()方法首先創(chuàng)建TempData對(duì)象(在Ruby On Rails中叫做Flash對(duì)象)。TempData可以用于保存下次請(qǐng)求必須的臨時(shí)數(shù)據(jù)(TempData和會(huì)話(huà)狀態(tài)差不多,不長(zhǎng)期占用內(nèi)存)。

接著,Execute()方法構(gòu)建請(qǐng)求的參數(shù)列表。這些參數(shù)從請(qǐng)求參數(shù)中提取,將會(huì)被作為方法的參數(shù)。參數(shù)會(huì)被傳入執(zhí)行的控制器方法。

Execute()通過(guò)對(duì)控制器類(lèi)進(jìn)行反射來(lái)找到控制器的方法??刂破黝?lèi)是我們寫(xiě)的。Execute()方法找到了我們控制器類(lèi)中的方法后就執(zhí)行它。Execute()方法不會(huì)執(zhí)行被裝飾NonAction特性的方法。

至此,就進(jìn)入了自己應(yīng)用程序的代碼。

步驟5:調(diào)用RenderView方法

通常,我們的控制器方法***會(huì)調(diào)用RenderView()或RedirectToAction()方法。RenderView()方法負(fù)責(zé)把視圖(頁(yè)面)呈現(xiàn)給瀏覽器。

當(dāng)我們調(diào)用控制器RenderView()方法的時(shí)候,調(diào)用會(huì)委托給當(dāng)前ViewEngine的RenderView()方法。ViewEngine是另外一個(gè)擴(kuò)展點(diǎn)。默認(rèn)的ViewEngine是WebFormViewEngine。然而,我們可以使用諸如Nhaml的其它ViewEngine。

WebForm的ViewEngine.RenderView()方法創(chuàng)建了一個(gè)叫做ViewLocator的類(lèi)來(lái)尋找視圖。然后,它使用BuildManager來(lái)創(chuàng)建ViewPage類(lèi)的實(shí)例。然后,如果頁(yè)面有ViewData就會(huì)設(shè)置ViewData。***,ViewPage 的RenderView()方法被調(diào)用。

ViewPage類(lèi)從System.Web.UI.Page基類(lèi)(和用于傳統(tǒng)ASP.NET的頁(yè)面一樣)派生。RenderView()方法做的***一個(gè)工作就是調(diào)用頁(yè)面類(lèi)的ProcessRequest()。調(diào)用視圖的ProcessRequest()生成內(nèi)容的方式和普通ASP.NET頁(yè)面生成內(nèi)容的方式一致。

可擴(kuò)展點(diǎn)

ASP.NET MVC生命周期在設(shè)計(jì)的時(shí)候包含了很多可擴(kuò)展點(diǎn)。我們可以自定義通過(guò)插入自定義類(lèi)或覆蓋既有類(lèi)來(lái)自定義框架的行為。下面是這些擴(kuò)展點(diǎn)的概要:

路由對(duì)象:當(dāng)我們創(chuàng)建路由表的時(shí)候,調(diào)用RouteCollection.Add()方法來(lái)增加新的路由對(duì)象。Add()方法接受了RouteBase對(duì)象。我們可以通過(guò)派生RouteBase基類(lèi)來(lái)實(shí)現(xiàn)自己的路由對(duì)象。

MvcRouteHandler :當(dāng)創(chuàng)建MVC應(yīng)用程序的時(shí)候,我們把URL映射到MvcRouteHandler對(duì)象上。然而,我們可以把URL映射到實(shí)現(xiàn)IRouteHandler接口的任何類(lèi)上。路由類(lèi)的構(gòu)造函數(shù)接受任何實(shí)現(xiàn)IRouteHandler接口的對(duì)象。

MvcRouteHandler.GetHttpHandler() : MvcRouteHandler 類(lèi)的GetHttpHandler()方法是virtual方法。默認(rèn)情況下,MvcRouteHandler返回MvcHandler。如果愿意的話(huà),我們可以覆蓋GetHttpHandler()方法來(lái)返回不同的Handler。

ControllerFactory :我們可以通過(guò)System.Web.MVC.ControllerBuilder.Current.SetControllerFactory()方法指定一個(gè)自定義類(lèi)來(lái)創(chuàng)建自定義的控制器工廠??刂破鞴S負(fù)責(zé)為某個(gè)控制器名和RequestContext返回控制器。

控制器:我們可以通過(guò)實(shí)現(xiàn)Icontroller接口來(lái)實(shí)現(xiàn)自定義控制器。這個(gè)接口只有一個(gè)Execute(ControllerContext controllerContext)方法。

ViewEngine:我們可以為控制器指定自定義的ViewEngine。通過(guò)為公共的Controller.ViewEngine屬性指定ViewEngine來(lái)把ViewEngine指定給控制器。ViewEngine必須實(shí)現(xiàn)IviewEngine接口,接口只有一個(gè)方法:RenderView(ViewContext viewContext)。

ViewLocator :ViewLocator把視圖名映射到實(shí)際視圖文件上。我們可以通過(guò)WebFormViewEngine.ViewLocator的屬性來(lái)執(zhí)行自定義的ViewLocator。

【編輯推薦】

  1. 為ASP.NET控件加入快捷菜單
  2. 在ASP.NET中使用Treeview控件和XML
  3. ASP.NET MVC實(shí)例和新RC版本中視圖方面的改進(jìn)
責(zé)任編輯:楊鵬飛 來(lái)源: Bolg
相關(guān)推薦

2010-04-02 09:02:02

ASP.NET MVC

2009-07-20 10:33:02

ASP.NET MVC

2009-07-23 18:14:17

MVC生命周期

2009-07-31 10:47:18

ASP.NET頁(yè)面生命

2009-07-23 10:23:44

2009-08-10 14:31:46

ASP.NET組件設(shè)計(jì)ASP.NET控件生命

2013-04-07 10:42:56

Asp.Net頁(yè)面周期

2009-08-04 16:50:15

ASP.NET頁(yè)面生命

2009-08-04 16:05:15

ASP.NET頁(yè)面生命

2009-08-04 17:49:31

Web Page生命周ASP.NET Pos

2009-08-03 14:18:40

ASP.NET編程模型ASP.NET頁(yè)面生命

2009-08-03 14:37:38

ASP.NET編程模型頁(yè)面生命周期

2011-06-21 10:26:37

2009-07-28 09:46:53

ASP.NET服務(wù)器控

2012-08-16 09:38:38

ASP.NET

2009-07-23 18:55:17

ASP.NET頁(yè)生命周

2010-03-19 09:17:16

ASP.NET MVC

2021-04-26 09:22:07

ASP.NET Cor服務(wù)周期

2009-07-31 17:53:39

ASP.NET線(xiàn)程安全

2009-09-10 09:50:47

ASP.NET MVC
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)