.NET (C#) Internals: ASP.NET 應用程序與頁面生命周期(意譯)

.NET (C#) Internals: ASP.NET 應用程序與頁面生命周期(意譯)1、引言2、兩個處理步驟2.1、創建ASP.NET環境2.2、用觸發的MHPM事件處理請求3、什麼事件中應該做什麼4、示例代碼5、深入ASP.NET頁面事件1、引言這篇文章我們將試圖理解,從用戶發送一個請求直到請求呈現到瀏覽器發生的事件的差異。因此,我們首先將介紹解ASP.NET請求的兩個概括的步驟,接下來我們將介紹『HttpHandler』,『HttpModule』和ASP.NET頁面對象發出的事件的差異。隨著我們的事件旅程,我們將理解這些事件的邏輯。2、兩個處理步驟ASP.NET請求處理可以總結為如下所示的兩個處理步驟。用戶發送一個請求到IIS:ASP.NET創建處理請求的環境。換句話說,創建應用程序對象、request、response和context對象去處理請求。一旦環境已經創建,請求通過使用modules、handlers和page對象的一系列事件處理。為了簡化可以稱為MHPM(module、handler、page、module event),我們將在後面詳細討論。圖1、ASP.NET請求處理的兩個步驟在接下來的各節,我們將知道更多關於這兩個步驟的細節。2.1、創建ASP.NET環境step 1:用戶發送一個請求到IIS。IIS首先檢查哪個ISAPI擴展可以處理這個請求,這取決於請求的文件擴展名。舉例來說,如果請求頁面是『.ASPX』,它將被傳送到『aspnet_isapi.dll』來處理。step 2:如果這是www站點的第一個請求,ApplicationManager類將創建一個應用程序域,www站點運行於其中。我們都知道在同一個IIS上,兩個web應用程序的應用程序域是獨立的(隔離的)。因此一個應用程序域中問題不會的影響到其它應用程序域。step 3:新建的應用程序域創建宿主環境,如HttpRuntime對象。一旦宿主環境被創建,必要的ASP.NET核心對象如HttpContext、HttpRequest和HttpRespone對象也被創建。step 4:一旦所有的ASP.NET核心對象被創建,HttpApplication對象將被創建去處理請求。如果系統中有global.asax文件,global.asax文件對象將被創建。【注意】:global.asax文件繼承自HttpApplication類;第一次ASP.NET頁面連接到應用程序,一個HttpApplication新實例將被創建。為了最大化性能,HttpApplication實例可能被多個請求重用。step 5:接下來HttpApplication對象分配給核心ASP.NET對象來處理頁面。step 6:然後HttpApplication通過HttpContext、HttpRequest和HttpRespone事件開始處理請求。它觸發MHPM事件處理請求。【更多細節】:http://msdn.microsoft.com/en-us/library/ms178473.aspx圖2、創建ASP.NET環境下圖解釋了ASP.NET請求的內部對象模型。最高層是ASP.NET運行時,它已經創建一個應用程序域(AppDomain),相應地有HttpRuntime包括request、respone、context對象。圖3、ASP.NET請求的內部對象模型2.2、用觸發的MHPM事件處理請求一旦創建了HttpApplication,它開始處理請求,它經歷3個不同的部分HttpModule、Page、HttpHandler。隨著它移動到這些部分,將調用不同的事件,開發人員可以擴展和定製同一邏輯。在我們前進之前讓我們了解什麼是HttpModule和HttpHandlers。他們幫組我們在ASP.NET頁處理的前後注入自定義邏輯。他們之間的主要差別是:(1)如果你想要注入的邏輯是基於像『.ASPX』、『.HTML』這樣的文件擴展名,使用HttpHandler。換句話說HttpHandler是基於處理器的擴展。(2)如果你想在ASP.NET管道事件中注入邏輯,使用HttpModule。換言之是基於處理器的事件。你可以點這了解他們之間更多的差異。下面是怎樣處理請求的邏輯流。有四個重要的步驟MHPM,解釋如下:Step 1(M HttpModule):客戶端請求處理開始。ASP.NET引擎開始和創建HttpModule發出事件(你可以注入定製邏輯)之前,有6個重要事件你可以使用:BeginRequest、AuthenticateRequest、AuthorizeRequest、ResolveRequestCache、AcquireRequestState和PreRequestHandlerExecute。Step 2(H HttpHandler):一旦上面6個事件觸發,ASP.NET引擎將調用ProcessRequest事件,即使你已經在項目中執行了HttpHandler。Step 3(P ASP.NET page):一旦HttpHandler邏輯執行,ASP.NET page對象被創建。ASP.NET page對象被創建,許多事件被觸發,你可以在這些頁面事件中寫我們自定義的邏輯。有6個重要事件給我們提供佔位,在ASP.NET頁中寫邏輯:Init、Load、Validate、Event、Render、Unload。你可以記住單詞SILVER來記這些事件,S-Start(沒有任何意義,僅僅是為了形成一個單詞),I(Init)、L(Load)、V(Validate)、E(Event)、R(Render)。Step 4(M HttpModule):一旦頁面對象執行了且從內存中卸載,HttpModule提供發送頁面執行事件,它們可用於注入自定義post-處理邏輯。有4個重要的post-處理事件,PostRequestHandlerExecute、PostRequestState、UpdateRequestCache、EndRequest。下圖展示了上面的過程。3、什麼事件中應該做什麼下面的表格展示了什麼事件中做什麼邏輯或代碼。SectionEventDescriptionHttpModuleBeginRequest此事件標誌著一個新的請求,他保證在每個請求中都有。HttpModuleAuthenticateRequest此事件標誌ASP.NET運行時準備驗證用戶。任何身份驗證代碼都可以在此注入。HttpModuleAuthorizeRequest此事件標誌ASP.NET運行時準備授權用戶。任何授權代碼都可以在此注入。HttpModuleResolveRequest在ASP.NET中我們通常使用OutputCache指令做緩存。在這個事件中,ASP.NET運行時確定是否能夠從緩存中載入頁面,而不是從頭開始生成。任何緩存的具體活動可以被注入這裡。HttpModuleAcquireRequestState此事件標誌著ASP.NET運行時準備獲得會話變數。可以對會話變數做任何你想要的處理。HttpModulePreRequestHandlerExecute恰好在ASP.NET 開始執行事件處理程序前發生。可以預處理你想做的事。HttpHandlerProcessRequestHttpHandler邏輯被執行。在這個部分我們將為每個頁面擴展名寫需要的邏輯。PageInit此事件發生在ASP.NET頁面且可以用來:1、動態地創建控制項,如果你一定要在運行時創建控制項;2、任何初始化設置3、母版頁及其設置在這部分中我們沒有獲得viewstate、postedvalues及已經初始化的控制項。PageLoad在這部分ASP.NET控制項完全被載入且在這裡你可以寫UI操作邏輯或任何其他邏輯。PageValidate如果在頁面上你有驗證器,你同樣想在這裡檢查。PageRender是時候將輸入發送到瀏覽器。如果你想對最終的HTML做些修改,你可以在這裡輸入你的HTML邏輯。PageUnload頁面對象從內存中卸載。HttpModulePostRequestHandlerExecute可以注入任何你想要的邏輯,在處理程序執行之後。HttpModuleReleaseRequestState想保存更新某些狀態變數,如會話變數。HttpModuleUpdateRequestCache在結束之前是否更新你的緩存。HttpModuleEndRequest這是將輸出發送到客戶端瀏覽器之前的最後一個階段。4、示例代碼點擊下載代碼,示例代碼展示了事件是怎樣觸發的。代碼中我們創建了一個HttpModule和HttpHandler,且我們顯示一個簡單的響應在所有的事件中。下面是HttpModule類,跟蹤所有的事件且添加到全局集合。HttpModule類public class clsHttpModule : IHttpModule{......void OnUpdateRequestCache(object sender, EventArgs a){objArrayList.Add("httpModule:OnUpdateRequestCache");}void OnReleaseRequestState(object sender, EventArgs a){objArrayList.Add("httpModule:OnReleaseRequestState");}void OnPostRequestHandlerExecute(object sender, EventArgs a){objArrayList.Add("httpModule:OnPostRequestHandlerExecute");}void OnPreRequestHandlerExecute(object sender, EventArgs a){objArrayList.Add("httpModule:OnPreRequestHandlerExecute");}void OnAcquireRequestState(object sender, EventArgs a){objArrayList.Add("httpModule:OnAcquireRequestState");}void OnResolveRequestCache(object sender, EventArgs a){objArrayList.Add("httpModule:OnResolveRequestCache");}void OnAuthorization(object sender, EventArgs a){objArrayList.Add("httpModule:OnAuthorization");}void OnAuthentication(object sender, EventArgs a){objArrayList.Add("httpModule:AuthenticateRequest");}void OnBeginrequest(object sender, EventArgs a){objArrayList.Add("httpModule:BeginRequest");}void OnEndRequest(object sender, EventArgs a){objArrayList.Add("httpModule:EndRequest");objArrayList.Add("<hr>");foreach (string str in objArrayList){httpApp.Context.Response.Write(str + "<br>") ;}}}下面是HttpHandler的代碼片段,它跟蹤ProcessRequest事件。HttpHandler代碼片段public class clsHttpHandler : IHttpHandler{public void ProcessRequest(HttpContext context){clsHttpModule.objArrayList.Add("HttpHandler:ProcessRequest");context.Response.Redirect("Default.aspx");}}我們也追蹤ASP.NET頁面的所有事件。public partial class _Default : System.Web.UI.Page{protected void Page_init(object sender, EventArgs e){clsHttpModule.objArrayList.Add("Page:Init");}protected void Page_Load(object sender, EventArgs e){clsHttpModule.objArrayList.Add("Page:Load");}public override void Validate(){clsHttpModule.objArrayList.Add("Page:Validate");}protected void Button1_Click(object sender, EventArgs e){clsHttpModule.objArrayList.Add("Page:Event");}protected override void Render(HtmlTextWriter output){clsHttpModule.objArrayList.Add("Page:Render");base.Render(output);}protected void Page_Unload(object sender, EventArgs e){clsHttpModule.objArrayList.Add("Page:UnLoad");}}下面顯示上面討論的所有事件的執行順序:5、深入ASP.NET頁面事件在前面部分我們已經知道ASP.NET頁面請求的整體事件流,但是我們沒有詳細討論,因此本節我們將深入了解。任何ASP.NET頁面有2個部分,一個是顯示在瀏覽器上的頁面,它有HTML標記、viewstate形式的隱藏值、HTML inputs上的數據。當頁面被發送時,在伺服器上這些HTML標記被創建到ASP.NET控制項且viewstate和表單數據捆綁在一起。一旦你得到這些伺服器控制項的後台代碼,你可以執行和寫你自己的邏輯和呈現返回給瀏覽器。現在這些HTML控制項在伺服器上作為ASP.NET控制項,ASP.NET頁面發出一些事件,我們可以注入自己的邏輯。根據任務/你要執行的邏輯,我們需要把這些邏輯放入適當的事件中。【注意】:大部分開發者直接使用Page_Load方法執行一切,這不是一個好的方法。因此,不是填充控制項、設置viewstate、應用主題等一切都發生在頁面載入上。因此,如果我們能在適當的事件中放入邏輯,將真正使你的代碼乾淨。、SeqEvents控制項初始化Viewstate可用表單數據可用什麼邏輯可以寫在這裡?1InitNoNoNo注意:你可以通過使用ASP.NET請求對象訪問表單數據等,但是不是通過伺服器控制項。動態地創建控制項,如果你一定要在運行時創建;任何初始化設置;母版頁及其設置。在這部分中我們沒有獲得viewstate、postedvalues及已經初始化的控制項。2Load View StateNot guaranteedYesNot guaranteed你可以訪問View State及任何同步邏輯,你希望viewstate被推倒後台代碼變數可以在這裡完成。3PostBackdataNot guaranteedYesYes捏可以訪問表單數據。任何邏輯,你希望表單數據被推倒後台代碼變數可以在這裡完成。4LoadYesYesYes在這裡你可以放入任何你想操作控制項的邏輯,如從資料庫填充combox、對grid中的數據排序等。這個事件,我們可以訪問所有控制項、viewstate、發送的值。5ValidateYesYesYes如果你的頁面有驗證器或者你想為你的頁面執行驗證,那就在這裡做吧。6EventYesYesYes如果這是通過點擊按鈕或下拉列表的改變的一個回發,相關的事件將被觸發。與事件相關的任何邏輯都可以在這裡執行。7Pre-renderYesYesYes如果你想對UI對象做最終的修改,如改變屬性結構或屬性值,在這些控制項保存到ViewState之前。8Save ViewStateYesYesYes一旦對伺服器控制項的所有修改完成,可以保存控制項數據到View State。9RenderYesYesYes如果你想添加一些自定義HTML到輸出,可以在這裡完成。10UnloadYesYesYes做任何你想做的清理工作。.NET Framework 4 - ASP.NET1 ASP.NET Application Life Cycle Overview for IIS 5.0 and 6.0This topic outlines the life cycle of ASP.NET applications, listing important life-cycle events and describing how code that you write can fit into the application life cycle. The information in this topic applies to IIS5.0 and IIS6.0. For information about the ASP.NET application life cycle in IIS7.0, seeASP.NET Application Life Cycle Overview for IIS 7.0.Within ASP.NET, several processing steps must occur for an ASP.NET application to be initialized and process requests. Additionally, ASP.NET is only one piece of the Web server architecture that services requests made by browsers. It is important for you to understand the application life cycle so that you can write code at the appropriate life cycle stage for the effect you intend.Application Life Cycle in GeneralThe following table describes the stages of the ASP.NET application life cycle.StageDescriptionUser requests an application resource from the Web server.The life cycle of an ASP.NET application starts with a request sent by a browser to the Web server (for ASP.NET applications, typically IIS). ASP.NET is an ISAPI extension under the Web server. When a Web server receives a request, it examines the file-name extension of the requested file, determines which ISAPI extension should handle the request, and then passes the request to the appropriate ISAPI extension. ASP.NET handles file name extensions that have been mapped to it, such as .aspx, .ascx, .ashx, and .asmx.NoteIf a file name extension has not been mapped to ASP.NET, ASP.NET will not receive the request. This is important to understand for applications that use ASP.NET authentication. For example, because .htm files are typically not mapped to ASP.NET, ASP.NET will not perform authentication or authorization checks on requests for .htm files. Therefore, even if a file contains only static content, if you want ASP.NET to check authentication, create the file using a file name extension mapped to ASP.NET, such as .aspx.NoteIf you create a custom handler to service a particular file name extension, you must map the extension to ASP.NET in IIS and also register the handler in your application"s Web.config file. For more information, seeHTTP Handlers and HTTP Modules Overview.ASP.NET receives the first request for the application.When ASP.NET receives the first request for any resource in an application, a class named ApplicationManager creates an application domain. Application domains provide isolation between applications for global variables and allow each application to be unloaded separately. Within an application domain, an instance of the class named HostingEnvironment is created, which provides access to information about the application such as the name of the folder where the application is stored.The following diagram illustrates this relationship:ASP.NET also compiles the top-level items in the application if required, including application code in the App_Code folder. For more information, see "Compilation Life Cycle" later in this topic.ASP.NET core objects are created for each request.After the application domain has been created and the HostingEnvironment object instantiated, ASP.NET creates and initializes core objects such as HttpContext, HttpRequest, and HttpResponse. The HttpContext class contains objects that are specific to the current application request, such as the HttpRequest and HttpResponse objects. The HttpRequest object contains information about the current request, including cookies and browser information. The HttpResponse object contains the response that is sent to the client, including all rendered output and cookies.An HttpApplication object is assigned to the requestAfter all core application objects have been initialized, the application is started by creating an instance of the HttpApplication class. If the application has a Global.asax file, ASP.NET instead creates an instance of the Global.asax class that is derived from the HttpApplication class and uses the derived class to represent the application.NoteThe first time an ASP.NET page or process is requested in an application, a new instance of HttpApplication is created. However, to maximize performance, HttpApplication instances might be reused for multiple requests.When an instance of HttpApplication is created, any configured modules are also created. For instance, if the application is configured to do so, ASP.NET creates a SessionStateModule module. After all configured modules are created, the HttpApplication class"s Init() method is called.The following diagram illustrates this relationship:The request is processed by the HttpApplication pipeline.The following events are executed by the HttpApplication class while the request is processed. The events are of particular interest to developers who want to extend the HttpApplication class.1. Validate the request, which examines the information sent by the browser and determines whether it contains potentially malicious markup. For more information, see ValidateRequest() andScript Exploits Overview.2. Perform URL mapping, if any URLs have been configured in the UrlMappingsSection section of the Web.config file.3. Raise the BeginRequest() event.4. Raise the AuthenticateRequest() event.5. Raise the PostAuthenticateRequest() event.6. Raise the AuthorizeRequest() event.7. Raise the PostAuthorizeRequest() event.8. Raise the ResolveRequestCache() event.9. Raise the PostResolveRequestCache() event.10. Based on the file name extension of the requested resource (mapped in the application"s configuration file), select a class that implements IHttpHandler to process the request. If the request is for an object (page) derived from the Page class and the page needs to be compiled, ASP.NET compiles the page before creating an instance of it.11. Raise the PostMapRequestHandler() event.12. Raise the AcquireRequestState() event.13. Raise the PostAcquireRequestState() event.14. Raise the PreRequestHandlerExecute() event.15. Call the ProcessRequest(HttpContext) method (or the asynchronous version System#Web#IHttpAsyncHandler#BeginProcessRequest(HttpContext, AsyncCallback, Object)) of the appropriate IHttpHandler class for the request. For example, if the request is for a page, the current page instance handles the request.16. Raise the PostRequestHandlerExecute() event.17. Raise the ReleaseRequestState() event.18. Raise the PostReleaseRequestState() event.19. Perform response filtering if the Filter() property is defined.20. Raise the UpdateRequestCache() event.21. Raise the PostUpdateRequestCache() event.22. Raise the EndRequest() event.23. Raise the PreSendRequestHeaders() event.24. Raise the PreSendRequestContent() event.Life Cycle Events and the Global.asax fileDuring the application life cycle, the application raises events that you can handle and calls particular methods that you can override. To handle application events or methods, you can create a file named Global.asax in the root directory of your application.If you create a Global.asax file, ASP.NET compiles it into a class derived from the HttpApplication class, and then uses the derived class to represent the application.An instance of HttpApplication processes only one request at a time. This simplifies application event handling because you do not need to lock non-static members in the application class when you access them. This also allows you to store request-specific data in non-static members of the application class. For example, you can define a property in the Global.asax file and assign it a request-specific value.ASP.NET automatically binds application events to handlers in the Global.asax file using the naming convention Application_event, such as Application_BeginRequest. This is similar to the way that ASP.NET page methods are automatically bound to events, such as the page"s Page_Load event. For details, seeASP.NET Page Life Cycle Overview.The Application_Start and Application_End methods are special methods that do not represent HttpApplication events. ASP.NET calls them once for the lifetime of the application domain, not for each HttpApplication instance.The following table lists some of the events and methods that are used during the application life cycle. There are many more events than those listed, but they are not commonly used.Event or methodDescriptionApplication_StartCalled when the first resource (such as a page) in an ASP.NET application is requested. The Application_Start method is called only one time during the life cycle of an application. You can use this method to perform startup tasks such as loading data into the cache and initializing static values.You should set only static data during application start. Do not set any instance data because it will be available only to the first instance of the HttpApplication class that is created.Application_eventRaised at the appropriate time in the application life cycle, as listed in the application life cycle table earlier in this topic.Application_Error can be raised at any phase in the application life cycle.Application_EndRequest is the only event that is guaranteed to be raised in every request, because a request can be short-circuited. For example, if two modules handle the Application_BeginRequest event and the first one throws an exception, the Application_BeginRequest event will not be called for the second module. However, the Application_EndRequest method is always called to allow the application to clean up resources.Init()Called once for every instance of the HttpApplication class after all modules have been created.Dispose()Called before the application instance is destroyed. You can use this method to manually release any unmanaged resources. For more information, seeCleaning Up Unmanaged Resources.Application_EndCalled once per lifetime of the application before the application is unloaded.Compilation Life CycleWhen the first request is made to an application, ASP.NET compiles application items in a specific order. The first items to be compiled are referred to as the top-level items. After the first request, the top-level items are recompiled only if a dependency changes. The following table describes the order in which ASP.NET top-level items are compiled.ItemDescriptionApp_GlobalResourcesThe application"s global resources are compiled and a resource assembly is built. Any assemblies in the application"s Bin folder are linked to the resource assembly.App_WebResourcesProxy types for Web services are created and compiled. The resulting Web references assembly is linked to the resource assembly if it exists.Profile properties defined in the Web.config fileIf profile properties are defined in the application"s Web.config file, an assembly is generated that contains a profile object.App_CodeSource code files are built and one or more assemblies are created. All code assemblies and the profile assembly are linked to the resources and Web references assemblies if any.Global.asaxThe application object is compiled and linked to all of the previously generated assemblies.After the application"s top level items have been compiled, ASP.NET compiles folders, pages, and other items as needed. The following table describes the order in which ASP.NET folders and items are compiled.ItemDescriptionApp_LocalResourcesIf the folder containing the requested item contains an App_LocalResources folder, the contents of the local resources folder are compiled and linked to the global resources assembly.Individual Web pages (.aspx files), user controls (.ascx files), HTTP handlers (.ashx files), and HTTP modules (.asmx files)Compiled as needed and linked to the local resources assembly and the top-level assemblies.Themes, master pages, other source filesSkin files for individual themes, master pages, and other source code files referenced by pages are compiled when the referencing page is compiled.Compiled assemblies are cached on the server and reused on subsequent requests and are preserved across application restarts as long as the source code is unchanged.Because the application is compiled on the first request, the initial request to an application can take significantly longer than subsequent requests. You can precompile your application to reduce the time required for the first request. For more information, seeHow to: Precompile ASP.NET Web Sites.Application RestartsModifying the source code of your Web application will cause ASP.NET to recompile source files into assemblies. When you modify the top-level items in your application, all other assemblies in the application that reference the top-level assemblies are recompiled as well.In addition, modifying, adding, or deleting certain types of files within the application"s known folders will cause the application to restart. The following actions will cause an application restart:· Adding, modifying, or deleting assemblies from the application"s Bin folder.· Adding, modifying, or deleting localization resources from the App_GlobalResources or App_LocalResources folders.· Adding, modifying, or deleting the application"s Global.asax file.· Adding, modifying, or deleting source code files in the App_Code directory.· Adding, modifying, or deleting Profile configuration.· Adding, modifying, or deleting Web service references in the App_WebReferences directory.· Adding, modifying, or deleting the application"s Web.config file.When an application restart is required, ASP.NET will serve all pending requests from the existing application domain and the old assemblies before restarting the application domain and loading the new assemblies.HTTP ModulesThe ASP.NET application life cycle is extensible through IHttpModule classes. ASP.NET includes several classes that implement IHttpModule, such as the SessionStateModule class. You can also create your own classes that implement IHttpModule.If you add modules to your application, the modules themselves can raise events. The application can subscribe to in these events in the Global.asax file by using the convention modulename_eventname. For example, to handle the Authenticate() event raised by a FormsAuthenticationModule object, you can create a handler named FormsAuthentication_Authenticate.The SessionStateModule class is enabled by default in ASP.NET. All session events are automatically wired up as Session_event, such as Session_Start. The Start() event is raised each time a new session is created. For more information, seeASP.NET Session State Overview.
推薦閱讀:

Asp.Net Core中間件攔截Http流
ASP.NET面試題(英文)
ASP.NET MVC 開篇
ASP.NET Web API 2
博客園 - 鳥食軒 - 在Apache環境下成功的運行ASP.NET

TAG:生命 | 程序 | .NET | ASP.NET | 生命周期 | 周期 | 頁面 |