欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
從底層角度看ASP.NET-A low-level Look at the ASP.NET...
從更低的角度
這篇文章在一個(gè)底層的角度來(lái)關(guān)注一個(gè)web請求怎樣到達asp.net框架,從web服務(wù)器,通過(guò)ISAPI??纯催@些后面發(fā)生了什么,讓我們停止對asp.net的黑箱猜想。
ASP.NET是一個(gè)非常強大用來(lái)創(chuàng )建web應用程序的平臺,它為創(chuàng )建web應用程序提供了大量的靈活強大的支持。大多數人僅僅熟悉表層的WebForm和webservice,他們位于整個(gè)ASP.NET架構的最表層。在這篇文章里,我將會(huì )描述非常底層的ASP.NET并且解釋一個(gè)web請求是如何從web服務(wù)器到達ASP.NET運行時(shí),并且通過(guò)ASP.NET管道(pipeline)處理請求的。
對我來(lái)說(shuō)理解一個(gè)平臺的內部機制,能夠然我自己得到相應的滿(mǎn)意和舒適,同時(shí)也可以幫助我們寫(xiě)出更好的應用程序。了解這些工具是怎樣作為整個(gè)框架的某一部分而互相配合,并且更加容易的找到問(wèn)題的解決方案,更加重要的,在發(fā)生錯誤的時(shí)候,能夠幫助你定位以及調試這個(gè)錯誤。這篇文章的目標就是從系統的角度來(lái)看ASP.NET,并且幫助理解,請求是如何到達ASP.NET處理管道的。就這點(diǎn)而言,我們將會(huì )看到核心引擎,以及一個(gè)web請求是如何終結的。很多東西都是你在日常的工作中不需要知道的,但是它有利于理解ASP.NET架構怎樣路由到你經(jīng)常編寫(xiě)的應用程序的高層代碼的。
大多數使用ASP.NET的人都是對Wenforms和WebService熟悉。這些高層的實(shí)現能夠簡(jiǎn)化創(chuàng )建以web為基礎的應用程序,并且,ASP.NET是一個(gè)驅動(dòng)引擎,提供了對web服務(wù)器的底層接口,也為你在你的程序中用到的典型的高層前端服務(wù)的路由機制提供接口。WebForm和WebService僅僅是兩個(gè)在A(yíng)SP.NET框架核心上構建的非常經(jīng)久耐用的HttpHandlers。
然而,ASP.NET在低層提供了更多的靈活性。HTTP Runtime和請求管道提供了所有的相同創(chuàng )建WebForm和WebService的能力,它們實(shí)際上也是由.NET托管代碼實(shí)現。而且,你如果決定自己定制、創(chuàng )建一個(gè)比WebForm稍低層的平臺,所有的ASP.NET的低層的這些功能、機制,你也同樣可以使用。
WebForm顯然是創(chuàng )建大多數web應用程序的最容易的方式,但是你在創(chuàng )建自定義內容的handlers或者對于進(jìn)、出內容需要特殊的處理,或者你需要為另外一個(gè)應用程序創(chuàng )建一個(gè)定制的應用程序接口,使用低層的handlers或者modules能夠給你更好的性能以及對一個(gè)web請求的更好的控制。你也可以繞過(guò)WebForm和WebService的這些高層實(shí)現提供的這些功能、機制直接在底層進(jìn)行操作。

什么是ASP.NET

讓我們以一個(gè)簡(jiǎn)單的定義開(kāi)始:什么事ASP.NET?我喜歡把ASP.NET定義如下:
ASP.NET是一個(gè)使用托管代碼完成的,從前到后處理web請求的,久經(jīng)考驗的框架。它并不僅僅是WebForm和WebService…
ASP.NET是一個(gè)請求處理引擎,它通過(guò)它的內部的管道將一個(gè)請求傳送到一個(gè)開(kāi)發(fā)者的代碼上。實(shí)際上這個(gè)引擎完全獨立于HTTP或者web服務(wù)器。事實(shí)上,HTTP Runtime是一個(gè)在IIS或者其他任何服務(wù)器之外的,您的應用程序的宿主環(huán)境。舉一個(gè)例子,您可以將ASP.NET runtime放到一個(gè)Windows窗口中(點(diǎn)擊獲得更多詳情http://www.west-wind.com/presentations/ASP.NETruntime/ASP.NETruntime.asp
運行時(shí)為請求通過(guò)這個(gè)管道提供了一個(gè)復雜而又優(yōu)雅的機制。有一系列的相關(guān)對象,大多數都是可以在請求的每一個(gè)層次,通過(guò)實(shí)現其子類(lèi)或者實(shí)現事件接口來(lái)進(jìn)行擴展。通過(guò)這個(gè)機制能夠接觸到非常低層的接口,例如緩存,權限驗證等。你甚至能在接受請求的前后過(guò)濾內容,或者將滿(mǎn)足特定要求的請求轉到你的代碼或者其他的URL地址。有很多不同的方法來(lái)完成相同的事情,而且所有的這些方法實(shí)現的都非常直接,這樣,就可以靈活的根據性能以及開(kāi)發(fā)難度來(lái)選擇最好的方法.

整個(gè)的ASP.NET引擎都是托管代碼完成的,并且,可以支持通過(guò)托管代碼進(jìn)行拓展
整個(gè)的ASP.NET引擎都是托管代碼完成的,并且,可以支持通過(guò)托管代碼進(jìn)行拓展.這是一個(gè)對.NET框架是否能夠開(kāi)發(fā)出久經(jīng)考驗的、性能良好的框架的有力的證明。然而,給人印象最深刻的部分是ASP.NET的深思熟慮的架構,能夠使得這個(gè)結構非常易用,提供了處理請求的任何一個(gè)部分的能力。
使用ASP.NET你能夠完成  以前是ISAPI擴展和ISAPI篩選器領(lǐng)域的工作,雖然帶有一些局限性,但是比ASP要好很多。ISAPI是一個(gè)非常底層的Win32形式的API,它僅有非常貧乏的接口,非常難創(chuàng )建經(jīng)久耐用的應用程序。由于ISAPI非常的底層而且非??焖?,它處在非托管開(kāi)發(fā)層。這樣ISAPI有些時(shí)候主要用做連接其他的應用程序平臺的橋。這并不意味著(zhù)ISAPI已經(jīng)死了。事實(shí)上ASP.NET在微軟的平臺上,正是通過(guò)ISAPI的一個(gè)擴展和ASP.NET的運行時(shí)和IIS進(jìn)行交互的。ISAPI提供了Web服務(wù)器的核心接口,并且ASP.NET使用非托管的ISAPI代碼來(lái)向客戶(hù)端接收,發(fā)送數據。ISAPI提供的數據,是通過(guò)一些通用的對象暴露出去的,像HttpRequest和HtttpReponse,他們通過(guò)托管代碼對象,以一個(gè)非常好的,易接觸的接口形式,對外暴露非托管代碼的內容。
 
從瀏覽器到ASP.NET
讓我們從一個(gè)典型的ASP.NET Web Request的生命周期的最初開(kāi)始。一個(gè)請求,在瀏覽器里,在一個(gè)用戶(hù)輸入一個(gè)URL地址或者點(diǎn)擊一個(gè)超鏈接,或者提交一個(gè)HTML表單(一個(gè)post類(lèi)型的請求)?;蛘咭粋€(gè)客戶(hù)端的程序會(huì )調用ASP.NET的WebService,這個(gè)WebService也使用過(guò)ASP.NET進(jìn)行服務(wù)的。在服務(wù)器端,IIS5或者6接收到請求。在最底層,ASP.NET通過(guò)一個(gè)ISAPI擴展和IIS進(jìn)行交互。這樣的一個(gè)請求通常會(huì )被路由到一個(gè)以aspx為擴展名的頁(yè)面文件,但是如何處理這個(gè)請求,完全取決與HTTP handler的實(shí)現,這個(gè)handler為了處理指定的擴展名而創(chuàng )立起來(lái)。在IIS里,.aspx 被‘應用程序擴展’(也可以成為腳本映射) 映射到ASP.NET ISAPI dll - ASP.NET_isapi.dll.每一個(gè)觸發(fā)ASP.NET的請求都是必須通過(guò)在A(yíng)SP.NET_isapi.dll指明和注冊的擴展名。
 
根據擴展名,ASP.NET將請求路由到相應的,負責響應請求的handler。舉一個(gè)例子,asmx這是一個(gè)WebService的擴展名,它不會(huì )被路由到磁盤(pán)上面的一個(gè)頁(yè)面文件,而是路由到一個(gè)WebService類(lèi)里面。其他很多的映射已經(jīng)被ASP.NET安裝了,而且你也可以定義你自己的。所有的這些HttpHandlers都是在A(yíng)SP.NET  ISAPI里面指出,從而在IIS里面被映射,或者在web.config文件里面設置,路由到指定的HTTP Handler的實(shí)現。每一個(gè)handler,是處理指定的擴展名的一個(gè).NET類(lèi),這個(gè)類(lèi)可以簡(jiǎn)單到一個(gè)HelloWorld程序,也可以非常復雜,像一個(gè)ASP.NET page類(lèi)或者 WebService 的實(shí)現?,F在,理解擴展名是這種映射機制的基礎,這種機制是ASP.NET用來(lái)從IIS獲得一個(gè)用戶(hù)請求然后將其路由到指定的處理請求的handler。

ISAPI是第一個(gè)也是性能最高的定制web請求處理的切入點(diǎn)。
ISAPI 連接
ISAPI是一個(gè)非常低層的非托管的win32API。這個(gè)接口根據ISAPI定義規范,非常的簡(jiǎn)單,還有優(yōu)化過(guò)的性能。他們非常的底層-處理指針,用函數指針來(lái)進(jìn)行回調-它們?yōu)殚_(kāi)發(fā)者和工具提供最底層的,最好性能的,來(lái)處理IIS的接口。由于ISAPI非常的底層,他并適合創(chuàng )建應用程序級別的代碼,而且,ISAPI趨向主要被用作 為高層工具提供應用程序服務(wù)器功能的 橋接口。舉個(gè)例子,ASP和ASP.NET都是建立在ISAPI上面,還有Cold Fusion,運行在IIS上面的,大多數的Perl,PHP以及JSP的實(shí)現還有很多的第三方的解決方案,比如我的Web Connection framework for Visual FoxPro都是建立在ISAPI上面的。ISAPI是一個(gè)為高層應用程序提供接口的非常優(yōu)秀的工具,這些接口抽象了ISAPI提供的信息。在A(yíng)SP.NET和ASP中,這些引擎將ISAPI提供的信息抽象為像Request和Response這樣的對象,使他們讀取到ISAPI的Request信息。把ISAPI想象成鉛錘。對于A(yíng)SP.NET來(lái)說(shuō),ISAPI dll非常瘦小,僅僅是作為一個(gè)路由機制,以管道形式傳送請求到ASP.NET運行時(shí),所有的重型的處理甚至請求的線(xiàn)程管理,都在A(yíng)SP.NET引擎和你的代碼中。
 
依照協(xié)議,ISAPI支持ISAPI擴展和ISAPI篩選器。擴展是一個(gè)請求處理接口,并且提供處理web服務(wù)器的傳入傳出的邏輯,它本質(zhì)上是一個(gè)事務(wù)接口。ASP.NET和ASP都是做為ISAPI擴展被實(shí)現的。ISAPI過(guò)濾器是一組接口,他們能 查看每一個(gè)進(jìn)入IIS的請求,修改內容,或者改變類(lèi)似于驗證功能的行為。順便提一句,在A(yíng)SP.NET中,通過(guò)兩個(gè)概念映射了類(lèi)似ISAPI的功能:HTTPHandlers(擴展)和HttpModules(篩選器)。一會(huì ),我們看詳細的內容。
 
ISAPI是標記著(zhù)ASP.NET的請求的初始代碼。ASP.NET映射了各種擴展名到ISAPI的擴展里,這些映射都在.NET Framework的目錄下:
<.NET FrameworkDir>\ASP.NET_isapi.dll
你可以交互式的在IIS服務(wù)管理器里面看到這些映射,如圖一.選擇你的網(wǎng)站,然后“主目錄”,“配置”,“映射”。


圖一: IIS 映射各種擴展名到ASP.NET ISAPI,像 .ASPX 。通過(guò)這個(gè)機制,請求在web服務(wù)器層被路由到ASP.NET的處理管道。
 
你不應該手動(dòng)的設置它們,因為.NET需要他們。另外你也可以使用ASP.NET_regiis.exe 工具來(lái)使得各種腳本映射得到正確的注冊:
 
cd <.NetFrameworkDirectory>
ASP.NET_regiis - i
 
這就將會(huì )為整個(gè)的站點(diǎn)注冊特定版本的ASP.NET運行時(shí),創(chuàng )建各種客戶(hù)端腳本庫。注意,這里是注冊在上面的文件夾安裝的特定版本的CLR 。ASP.NET_regiis命令的選項允許你可以單獨的設置一個(gè)虛擬目錄。每一個(gè)版本的.NET框架都有他自己版本的ASP.NET_regiis,你需要運行一個(gè)恰當版本的來(lái)注冊一個(gè)網(wǎng)站或者一個(gè)虛擬目錄。以ASP.NET2.0為例,你可以在IIS配置頁(yè)面里面的ASP.NET選項選擇.NET的版本。
 
IIS5和IIS6工作方式不同
當一個(gè)請求進(jìn)入,IIS檢查腳本映射,然后將請求路由到ASP.NET_isapi.dll。這個(gè)DLL進(jìn)行的操作在IIS6和IIS5中明顯不同,圖2大概的展示了這個(gè)流程。
 
IIS5中直接宿主ASP.NET_isapi.dll在inetInfo.exe進(jìn)程中,或者一個(gè)獨立的進(jìn)程中。當第一個(gè)請求來(lái)到這個(gè)DLL文件的時(shí)候,將會(huì )產(chǎn)生另外的一個(gè)新的進(jìn)程– ASP.NET_wp.exe –并且路由請求到這個(gè)新生成的進(jìn)程中。這個(gè)進(jìn)程一次的加載,宿主.NET運行時(shí)。每一個(gè)請求都是先來(lái)到ISAPI然后通過(guò)命名管道路由到工作進(jìn)程

圖二– 從IIS到ASP.NET運行時(shí)的. IIS 5 and IIS 6以不同的方式處理 ASP.NET,但是總的來(lái)說(shuō),一旦到了ASP.NET的管道,就相同了。

IIS6,不像以前的服務(wù)器,它是完全為ASP.NET做過(guò)優(yōu)化的
IIS 6 –應用程序池萬(wàn)歲
IIS6明顯的改變了處理模型,IIS不再像ISAPI的擴展一樣直接的處理任何不相關(guān)的可執行代碼。取而代之的是,IIS6總是創(chuàng )建一個(gè)獨立的工作進(jìn)程—一個(gè)應用程序池—并且所有的請求都在這個(gè)進(jìn)程里面,包括ISAPI dll的執行。
應用程序池是IIS6的一個(gè)重要改善,因為它們允許非常細粒度的控制指定進(jìn)程執行的東西??梢詾槊恳粋€(gè)虛擬目錄或者一個(gè)站點(diǎn)設置應用程序池,所以你能夠將每一個(gè)web應用程序分割到每一個(gè)進(jìn)程中,這個(gè)進(jìn)程和其他的應用程序的進(jìn)程完全獨立。如果其中的一個(gè)進(jìn)程死掉了,也不會(huì )影響到其他的進(jìn)程。
 
另外,應用程序池是高度可設置化的。你可以通過(guò)設置它的執行模擬級別 來(lái)設置其執行的安全環(huán)境,你可以為每一個(gè)Web應用程序定制權限。為ASP.NET的一個(gè)重要的改進(jìn)就是應用程序池取代了大多數的在machine.config的進(jìn)程模型。這在IIS里面比較難于管理,因為這個(gè)設置是全局的,而且不能在應用程序web.config中被繼承。當IIS6運行的時(shí)候,進(jìn)程模型設置大部分被忽略了忽略,取而代之的是從應用程序池中讀取。我這里是說(shuō)“大部分”,對于一些設置,像進(jìn)程池的大小,IO線(xiàn)程仍舊在里面(配置文件)設置,因為應用程序池里面沒(méi)有對應的設置。
 
因為應用程序池是外部的可執行的,而且這些可以很容易的進(jìn)行監視和管理。IIS6提供了一些健康檢測,重啟,超時(shí)的選項,這些可以檢測,大多數可以修正應用程序的錯誤。最后,IIS6的應用程序池并不依賴(lài)COM+,和IIS5的獨立進(jìn)程一樣,它改進(jìn)了性能和穩定性,尤其是內部使用了COM對象的應用程序。
 
盡管IIS6的應用程序池區分于可執行文件,他們通過(guò)直接的接觸HTTP.SYS核心模塊,而進(jìn)行了高度的HTTP操作優(yōu)化。進(jìn)入的請求,直接的路由到相應的應用程序池。InetInfo僅僅扮演了一個(gè)管理、設置服務(wù)-大多說(shuō)交互實(shí)際發(fā)生在HTTP.SYS和應用程序之間,所有的這些構成了一個(gè)比IIS5更加穩定,更加高性能的環(huán)境。尤其是對于一些靜態(tài)內容和ASP.NET應用程序。
 
一個(gè)IIS6的應用程序池也有ASP.NET內在的認識,而且一個(gè)ASP.NET能夠和新的底層的API進(jìn)行交互,這使得ASP.NET直接接觸到HTTP Cache的API,也就使得能夠從ASP.NET層來(lái)控制Web服務(wù)器的緩存。
 
在IIS6,ISAPI擴展運行在一個(gè)應用程序池的工作進(jìn)程中。.NET運行時(shí)也運行在這個(gè)進(jìn)程,所以.NET運行時(shí)和ISAPI 擴展的交互是進(jìn)程內的,這樣肯定是比一定要使用命名管道接口的IIS5效率更高。盡管IIS兩個(gè)版本的宿主模型是不同的,但是到達托管代碼之后都是相同的了,只有在做請求路由的時(shí)候有一些不同。

ISAPIRuntime.ProcessRequest() 方法是進(jìn)入ASP.NET的第一個(gè)入口
進(jìn)入到.NET運行時(shí)
實(shí)際上進(jìn)入.NET運行時(shí),是通過(guò)一系列沒(méi)有給出文檔說(shuō)明的類(lèi)和接口。通過(guò)微軟,很少能夠了解這些接口和類(lèi),而且微軟并不想談?wù)撨@些細節,因為他們認為這些實(shí)現的細節幾乎對創(chuàng )建一個(gè)ASP.NET應用程序沒(méi)有影響。
 
工作進(jìn)程ASP.NET_WP.EXE (IIS5)和W3WP.EXE (IIS6)宿主.NET運行時(shí),并且ISAPI DLL 通過(guò)底層的COM調用了一些少量的非托管接口,而最終調用到了一個(gè)ISAPIRuntime的子類(lèi)。第一個(gè)入口就是這個(gè)沒(méi)有文檔說(shuō)明的ISAPIRuntime類(lèi),它通過(guò)COM將IISAPIRuntime接口暴露給調用者。這些COM接口,底層的以不了解的接口,意味著(zhù)從ISAPI擴展到ASP.NET的內部調用。圖3顯示了這個(gè)接口,在Lutz Roeder的優(yōu)秀的.NET Reflector 工具(http://www.aisto.com/roeder/dotnet/)。反射程序集視圖和反編譯器,這使得我們能夠非常容易的看到反編譯的代碼(用IL,C#,VB),這是一個(gè)非常好的方法來(lái)談就這樣的過(guò)程。

圖3 –如果你想深入研究底層的接口,打開(kāi)Reflector,并且打開(kāi) System.Web.Hosting 命名空間。進(jìn)入ASP.NET的入口點(diǎn)通過(guò)COM接口而被ISAPI dll調用,這就獲得了一個(gè)非托管的指針,指向了ISAPI ECB.。ECB包含了訪(fǎng)問(wèn)ISAPI的全部接口,能夠獲得請求的數據,也能夠將數據返回給IIS。
 
IISAPIRuntime接口在ISAPI擴展的非托管代碼和托管代碼之間。如果你看一個(gè)這個(gè)類(lèi),你會(huì )發(fā)現有一個(gè)簽名如下的方法:
 
[return: MarshalAs(UnmanagedType.I4)]
int ProcessRequest([In] IntPtr ecb,
                   [In, MarshalAs(UnmanagedType.I4)] int useProcessModel);
 
ecb這個(gè)參數是ISAPI擴展控制模塊(Extension Control Block –ECB),這個(gè)方法將非托管的資源傳到ProcessRequest方法中。這個(gè)方法獲得ECB并且 通過(guò)Request和Response對象將它作為輸入輸出的基礎。一個(gè)ISAPI ECB包含了所有的底層請求信息,包括服務(wù)器信息,一個(gè)來(lái)組織變量的輸入流同時(shí)也有一個(gè)用來(lái)寫(xiě)回數據給客戶(hù)端的輸出流。這個(gè)單獨的ecb基本提供了所有的ISAPI請求的所有的功能,而ProcessRequest方法是這個(gè)資源和托管代碼交互的出口和入口。
 
ISAPI擴展異步的處理請求。這個(gè)模型中,ISAPI擴展立刻回報給工作進(jìn)程或者IIS線(xiàn)程,而保持當前的請求的ECB存活。ECB包括一個(gè)機制允許ISAPI知道請求已經(jīng)完成(通過(guò)ecb.ServerSupportFunction),然后釋放ECB。這個(gè)異步處理立刻釋放ISAPI工作進(jìn)程,并且卸載進(jìn)程,而轉到由一個(gè)ASP.NET管理的獨立的線(xiàn)程。
 
ASP.NET接收到這個(gè)ecb引用,用它來(lái)獲取一些關(guān)于當前請求的信息,比如服務(wù)器變量,POST數據,也包括向服務(wù)器返回輸出數據。ECB存活到請求完成,或者IIS超時(shí)并且,ASP.NET會(huì )繼續和其進(jìn)行交互,直至請求完畢。輸出被寫(xiě)入到ISAPI的輸出流(ecb.WriteClient()),并且,當請求完成的時(shí)候,ISAPI擴展被通知請求完成,ECB可以被釋放。這個(gè)實(shí)現非常的高效,因為.NET類(lèi)完全扮演的是對高性能的非托管代碼簡(jiǎn)單的封裝,

加載.NET - 有一些神秘Loading .NET
讓我們回到這里的一個(gè)步驟:我跳過(guò)了.NET運行時(shí)是怎么加載的。這里的事情有一點(diǎn)模糊,這個(gè)過(guò)程,我沒(méi)有獲得任何的文檔,并且我們在談本地代碼,而又沒(méi)有簡(jiǎn)單的方法反編譯ISAPI DLL把它找出來(lái)。
 
我的最好的猜想是,當第一個(gè)ASP.NET映射擴展名被請求的時(shí)候,ISAPI擴展引導了.NET運行時(shí)。一旦這個(gè)運行時(shí)存在了之后,如果當前沒(méi)有,非托管代碼可以為給定的虛擬路徑請求一個(gè)ISAPIRuntime的實(shí)例對象。每一個(gè)虛擬目錄都會(huì )有它自己的AppDomain(應用程序域),在A(yíng)ppDomain里,ISAPIRuntime存在于一個(gè)獨立的應用程序引導的過(guò)程。實(shí)例化看起來(lái)像發(fā)生在COM里面,因為接口方法是一個(gè)COM可調用的方法。
 
為了創(chuàng )建ISAPIRuntime實(shí)例,System.Web.Hosting.AppDomainFactory.Create()方法被調用,當某一個(gè)虛擬目錄第一次被請求的時(shí)候。這開(kāi)始了‘應用程序’引導過(guò)程。這個(gè)調用獲得了參數的類(lèi)型,模塊的名稱(chēng)以及虛擬路徑的信息—對于應用程序來(lái)說(shuō),這個(gè)ASP.NET用來(lái)創(chuàng )建一個(gè)AppDomain以及運行指定虛擬目錄的ASP.NET應用程序。這個(gè)HttpRuntime派生對象在一個(gè)新的AppDomain里面被創(chuàng )建。每一個(gè)虛擬目錄都被宿主在一個(gè)獨立的AppDomain中,僅僅加載指定的應用程序的請求。ISAPI擴展來(lái)管理HttpRuntime對象的實(shí)例,路由相應的請求到正確的請求的虛擬路徑上。

圖4 – 從ISAPI請求到ASP.NET的HTTP管道的傳輸過(guò)程,使用到了一些沒(méi)有文檔說(shuō)明的類(lèi)和接口,并且需要一些工廠(chǎng)方法調用。通過(guò)其調用者把一個(gè)引用放在IISAPIRuntime接口中(這個(gè)接口觸發(fā)了ASP.NET請求處理)每一個(gè)Web應用程序運行在其自身的AppDomain中.
回到運行時(shí)
在這時(shí),我們已經(jīng)有了一個(gè)被ISAPI擴展激活,可被其調用的ISAPIRuntime的實(shí)例。一旦運行時(shí)運行起來(lái),ISAPI代碼將會(huì )調用到ISAPIRuntime.ProcessRequest()這個(gè)方法,這個(gè)方法是真正的進(jìn)入ASP.NET管道的入口。這個(gè)流程已經(jīng)顯示在圖4中。
 
記住,ISAPI是一個(gè)多線(xiàn)程的,這樣請求將會(huì )以多線(xiàn)程的方式進(jìn)如ASP.NET,通過(guò)ApplicationDomainFactory.Create()返回的引用。列表1顯示了IsapiRuntime.ProcessRequest反編譯的結果,這個(gè)方法接收一個(gè)ISAPI ecb對象,這個(gè)方法是線(xiàn)程安全的,所以,多線(xiàn)程的ISAPI可以同時(shí)的安全的調用這個(gè)單獨返回的對象實(shí)例。
Listing 1: 處理請求的方法獲得了一個(gè)ISAPI Ecb并且將其傳入工作進(jìn)程

Code

這里的代碼并不重要,并且記住,這是你將從來(lái)不會(huì )直接接觸到的,反編譯出來(lái)的框架內部的代碼,而且這些代碼可能在以后會(huì )改變。這意味著(zhù)證實(shí)在后臺發(fā)生了什么。ProcessRequest接收到非托管的ECB引用,并且將它傳送到ISAPIWorkerRequest對象中,這個(gè)對象負責為當前請求創(chuàng )建請球上下文,就像在Listing2中顯示的一樣。
 
System.Web.Hosting.ISAPIWorkerRequest類(lèi)是HttpWorkerRequest的一個(gè)抽象子類(lèi)。它的職責是為輸入輸出創(chuàng )建一個(gè)抽象的視圖,這個(gè)作為整個(gè)web應用程序的輸入。注意另外一個(gè)工廠(chǎng)方法: CreateWorkerRequest,做為第二個(gè)參數,它接收到了要創(chuàng )建的worker request的類(lèi)型,這里有三種不用的版本:ISAPIWorkerRequestInProc, ISAPIWorkerRequestInProcForIIS6, ISAPIWorkerRequestOutOfProc。這個(gè)對象在每一個(gè)請求進(jìn)來(lái)之后被創(chuàng )建,這個(gè)對象是Request和Response對象基礎,他們從WorkerRequest里接收他們的數據和流。
 
這個(gè)HttpWorkerRequest抽象類(lèi)用來(lái)為底層的接口提供一個(gè)高層的抽象,所以不管這個(gè)數據是來(lái)自一個(gè)CGI Web服務(wù)器,一個(gè)瀏覽器,或者一些訂制的機制。關(guān)鍵的是ASP.NET能夠以同樣的方式來(lái)獲得信息。
 
對于IIS的抽象,以一個(gè)ISAPI ECB模塊。在我們的請求過(guò)程中,ISAPIWorkRequst和IISAPI ECB交互,當需要的時(shí)候,通過(guò)它獲得數據。Listing2顯示展示了如何獲得query string 的值。
Listing 2: 一個(gè)使用非托管的ISAPIWorkerRequest 的方法

Code

ISAPIWorkerRequest實(shí)現了一個(gè)高層的封裝的方法,這個(gè)方法調用底層的用來(lái)和訪(fǎng)問(wèn)底層非托管的API的Core方法。Core 方法在ISAPIWorkerRequest實(shí)例的子類(lèi)中實(shí)現,這樣,為其宿主的環(huán)境提供實(shí)現方法。這樣構造了一個(gè)更加容易插拔的環(huán)境,方便添加一些新的服務(wù)器或者服務(wù)ASP.NET的其他平臺的接口的實(shí)現。也有一個(gè)輔助類(lèi)System.Web.UnsafeNativeMethods。很多的這些方法,他們就是通過(guò)操作ISAPI ECB結構體來(lái)完成對ISAPI擴展的調用。

HttpRuntime, HttpContext, and HttpApplication
當一個(gè)請求到達,被路由到ISAPIRuntime.ProcessRequest()方法。這個(gè)方法繼而調用HttpRuntime.ProcessRequest,這個(gè)方法做了很多重要的事情(使用Reflector 查看System.Web.HttpRuntime.ProcessRequestInternal):
 
•為請求創(chuàng )建一個(gè)新的HttpContext實(shí)例
•得到一個(gè)HttpApplication 實(shí)例
•調用 HttpApplication.Init() 來(lái)建立管道事件。
•Init() 觸發(fā) HttpApplication.ResumeProcessing(),這個(gè)方法開(kāi)始ASP.NET管道處理
 
首先,一個(gè)新的HttpContext對象被封裝了ISAPI ECB的 ISAPIWorkerRequest創(chuàng )建,傳遞。這個(gè)Context在整個(gè)的請求生命周期中都可用,總是可以通過(guò)靜態(tài)的HttpContext.Current 屬性來(lái)獲得。就像名字提示的,HttpContext對象表示了當前激活的請求的上下文,因為它包含了在請求的生命周期中,所有的你要接觸到的重要的典型的對象: Request, Response, Application, Server, Cache.在處理請求的任何時(shí)候,HttpContext.Current讓你接觸到所有的這些對象。
 
HttpContext對象同時(shí)包含了一個(gè)非常有用的集合,允許你用來(lái)存儲一些請求指定的數據。Context對象從請求周期被創(chuàng )建,當請求完成的時(shí)候釋放,所以存儲在這個(gè)集合的數據僅僅對應當前的請求。一個(gè)很好的應用的例子是一個(gè)時(shí)間請求記錄的機制,這里你想記錄請求開(kāi)始和請求結束的時(shí)間,通過(guò)在Listing3所示,在Global.asax 里面,Application_BeginRequest 和Application_EndRequest 方法。HttpContext是你的朋友,你可以自由的使用,在不同的請求或者頁(yè)面處理的部分。

Listing 3 – 使用 HttpContext.Items 結合來(lái)讓你在管道事件之間保存數據

Code

一旦Context對象被創(chuàng )立,ASP.NET需要路由進(jìn)入的請求到相應的應用程序/虛擬目錄,通過(guò)一個(gè)HttpApplication對象。每一個(gè)ASP.NET應用程序被需建立一個(gè)虛擬目錄(或者根根目錄)每一個(gè)‘application’獨立的處理。

HttpApplication像一個(gè)典禮的主人,處理動(dòng)作在這里開(kāi)始

你的域的主人: HttpApplication
每一個(gè)請求都被路由到一個(gè)HttpApplication對象。HttpApplicationFactory類(lèi)根據你的ASP.NET應用程序的負載情況,為其創(chuàng )建一個(gè)HttpApplication對象池,并且為每一個(gè)請求處理這些引用。這個(gè)池的容量受限于設置在machine.config的ProcessModel鍵里面的MaxWorkerThreads的值,默認值是20.
 
然而這個(gè)池只啟動(dòng)了少量對象,通常是一個(gè)然后同時(shí)進(jìn)入的請求多了,池中對象將會(huì )增長(cháng)。池是被監視的,在負載量大的時(shí)候,將會(huì )增長(cháng)到它的容量的最大值,當負載下降的時(shí)候,池的容量又會(huì )降低。
 
HttpApplication是你指定的Web應用程序的外部容器,并且它映射到定義在Global.asax的文件中。他是進(jìn)入HttpRuntime的第一個(gè)點(diǎn),如果你看Global.asax(或者其后置代碼)你會(huì )發(fā)現,他是派生自HttpApplication的一個(gè)類(lèi):public class Global : System.Web.HttpApplication
HttpApplication的主要目的是扮演了Http管道的事件控制者,所以它的接口主要由事件組成。事件是多方面的,包括:
•BeginRequest
•AuthenticateRequest
•AuthorizeRequest
•ResolveRequestCache
•AquireRequestState
•PreRequestHandlerExecute
•Handler Execution
•PostRequestHandlerExecute
•ReleaseRequestState
•UpdateRequestCache
•EndRequest
 
這些事件都在Global.asax文件中通過(guò)以Application_為前綴的空方法實(shí)現。舉個(gè)例子,Application_BeginRequest(), Application_AuthorizeRequest().這樣的處理方法,非常的方便,因為在應用程序中,他們經(jīng)常會(huì )被用到,這樣你就不用顯示的創(chuàng )建事件處理的委托。
 
理解每一個(gè)ASP.NET虛擬用應程序運行在它自己的AppDomain中,然而在這個(gè)AppDomain中,有多個(gè)HttpApplication實(shí)例在同時(shí)運行,被一個(gè)ASP.NET的一個(gè)池來(lái)進(jìn)行管理。這樣,多個(gè)請求就可以同時(shí)被處理,而且沒(méi)有互相的影響。
來(lái)看一看AppDomain,線(xiàn)程和HttpApplication的關(guān)系,看看Listing4的代碼。
Listing 4 – 顯示了AppDomain,線(xiàn)程和HttpApplication實(shí)例的關(guān)系

Code

這部分代碼運行的結果在圖5中顯示,在兩個(gè)不同的瀏覽器中來(lái)訪(fǎng)問(wèn)這個(gè)示例頁(yè)面,來(lái)看這不用的Id


圖 5 –通過(guò)同時(shí)用兩個(gè)瀏覽器訪(fǎng)問(wèn),你可以看到AppDomain,Application池還有請求進(jìn)程怎樣互相影響,當多個(gè)請求到達的時(shí)候,你會(huì )發(fā)現線(xiàn)程,Application的Id都改變了,AppDomain卻保持不變。
 
你會(huì )注意到,AppDomain 的ID保持不變,而HttpApplication的ID在大多數請求中都變化了,盡管他們有可能會(huì )重復。這些HttpApplication用過(guò)了,會(huì )在后面的請求中復用,所以Id是會(huì )重復出現的。注意,Application實(shí)例并不綁定到指定的線(xiàn)程,他們只是被分配到當前請求的線(xiàn)程中。
 
線(xiàn)程來(lái)自 .NET的ThreadPool,而且,默認的是Multithreaded Apartment (MTA)這種形式的線(xiàn)程。你可以在A(yíng)SP.NET頁(yè)面中重寫(xiě)這部分,通過(guò)在@Page 指令設置ASPCOMPAT="true" 屬性,ASPCOMPAT意味著(zhù)提供給COM組建一個(gè)安全的環(huán)境來(lái)運行,并且,ASPCOMPAT使用特殊的Single Threaded Apartment (STA)線(xiàn)程來(lái)服務(wù)這些請求。STA的線(xiàn)程被擱置、合并,因為他們需要特殊的處理。
 
事實(shí)上,HttpApplication對象都在同一個(gè)AppDomain中非常重要。這正是ASP.NET怎樣保證修改了web.config或者獨立的頁(yè)面,可以被整個(gè)的AppDomain所識別。在web.config里面修改值,可以引起AppDomain的關(guān)閉和重啟,這使得所有的HttpApplication都發(fā)現了這個(gè)變化,因為AppDomain重新加載的時(shí)候,他重新讀取了信息。所有的靜態(tài)成員都重新加載了,因為AppDomain重新加載,所以,應用程序從應用程序配置文件讀取設置的時(shí)候這些值都被更新了。
 
來(lái)看這個(gè)例子。訪(fǎng)問(wèn)ApplicationPoolsAndThreads.aspx頁(yè)面,并且注意AppDomain的Id。然后修改一下web.config(添加一個(gè)空格并且保存)。然后重新讀取這個(gè)頁(yè)面,你會(huì )發(fā)現AppDomain已經(jīng)被重新創(chuàng )建了。
 
本質(zhì)上,當這發(fā)生后,web應用程序/虛擬目錄完全的‘重啟’了。所有的已經(jīng)在管道中的請求,將會(huì )繼續的通過(guò)現在已經(jīng)存在的管道繼續運行,同時(shí),所有的新的請求都會(huì )被路由到新的AppDomain。為了處理那些‘掛起的請求’,在這些請求超時(shí)后或者甚至請求還在進(jìn)行的時(shí)候,ASP.NET會(huì )強制關(guān)閉舊的AppDomain。這樣,實(shí)際上在某一特定時(shí)間點(diǎn),可以存在兩個(gè)相同的AppDomain,為同一個(gè)HttpApplication服務(wù),舊的AppDomain關(guān)閉,新的AppDomain里面的Application對象將會(huì )急劇增加。兩個(gè)AppDomain都繼續服務(wù),直到舊的一個(gè)將所有的請求都運行完畢,舊的將會(huì )被關(guān)閉,只留下新的AppDomain。

ASP.NET管道的流程

HttpApplication通過(guò)觸發(fā)指示你的應用程序狀態(tài)的事件,來(lái)負責請求的流程。這發(fā)生在HttpApplication.Init()方法中(用Reflector看System.Web.HttpApplication.InitInternal 和 HttpApplication.ResumeSteps() ),這個(gè)方法連續的創(chuàng )建并觸發(fā)了一系列的事件,包括了調用執行所有的handlers.事件處理自動(dòng)的映射在global.asax里面的事件,并且,他們也映射所有已經(jīng)附加了的HTTPModule,本質(zhì)上,HTTPModule是一個(gè)形象化了事件槽。
 
HttpModules 和 HttpHandlers a都通過(guò)web.config里面條目而被動(dòng)態(tài)加載,并且將其綁定到事件鏈。HttpModules是實(shí)際的HttpApplication的事件處理者,而HttpHandlers是一個(gè)終點(diǎn),用來(lái)處理‘應用程序級的請求處理’的。HttpModules 實(shí)際是HttpApplication的事件處理器。
Modules 和 Handlers的加載,附加到調用鏈都做為HttpApplication.Init()方法的一部分、圖6顯示了各種事件以及他們出發(fā)的時(shí)間和觸發(fā)影響的部分。


圖 6 – ASP.NET HTTP管道的事件流程。HttpApplication對象的事件驅動(dòng)貫穿管道。 Http Modules能夠攔截這些事件,進(jìn)而重寫(xiě)或者增強已有的功能。
HttpContext, HttpModules 和 HttpHandlers
HttpApplication自身并不知道傳送進(jìn)來(lái)的數據,他僅僅是一個(gè)通信對象,通過(guò)事件來(lái)進(jìn)行交互。他觸發(fā)事件,并且將信息通過(guò)HttpContext對象傳遞到被調用的方法中。當前請求的狀態(tài)數據存儲在我們前面提到的Httpcontext對象。它提供了所有請求的數據,并且在管道中,伴隨著(zhù)每一個(gè)請求從開(kāi)始到結束。圖7顯示了通過(guò)ASP.NET管道的流程,注意Context對象從開(kāi)始到請求的結束,都可以用來(lái)存儲信息,在一個(gè)事件方法中存貯信息,在后面的事件方法中獲得這個(gè)數據。
 
一旦管道開(kāi)始,HttpApplication如圖6一樣,開(kāi)始一個(gè)接著(zhù)一個(gè)的觸發(fā)事件。每一個(gè)事件處理器被調用,如果事件被調用這些處理器執行他們的任務(wù)。這個(gè)過(guò)程的主要目的是最終調用HttpHandler處理一個(gè)請求。Handlers是處理ASP.NET請求的核心的機制,經(jīng)常位于應用程序級代碼的執行。記住,ASP.NET 頁(yè)面和WebService框架,都是作為HTTPHandler的實(shí)現,在這里請求的核心處理過(guò)程被執行。Modules往往是更核心的性質(zhì),用來(lái)準備或者發(fā)送處理交付于Handlers的Context。ASP.NET中,典型的默認的Handlers是Authentication, pre-processing的Caching 和 發(fā)送處理請求的編碼機制。
 
有很多的信息在HttpHandlers 和 HttpModules中,但是為了保持這篇文章的一個(gè)合理的長(cháng)度,我下面只是簡(jiǎn)短介紹一下handlers。
HttpModules
隨著(zhù)請求通過(guò)管道,一系列的事件在HttpApplication對象中被觸發(fā)。我們已經(jīng)在Global.asax中看到了這些事件。這種方法是應用程序指定的,這樣,就不一定總是你想要的。如果你想創(chuàng )建一個(gè)廣義的HttpApplication事件處理,而且能夠可插拔的放到任何一個(gè)應用程序中,你可以使用HttpModules,他們是可以復用的,而且,不需要程序代碼指定,只需要在web.config里面設置一下。
 
Modules本質(zhì)上像篩選器,就像一個(gè)在A(yíng)SP.NET請求層的ISAPI Filter。Modules允許附加事件到每一個(gè)通過(guò)ASP.NET HttpApplication對象的請求。這些Module在外部的程序集的類(lèi)里面,在web.config里面設置,并且當應用程序啟動(dòng)的時(shí)候,隨著(zhù)應用程序的啟動(dòng)而加載。通過(guò)實(shí)現指定的接口和方法,將事件添加到HttpApplication事件鏈中。多個(gè)HttpModules能夠附加事件處理代碼到相同的事件上,這些附加的事件處理的順序根據在web.config里面設置的一樣:

<configuration>
  
<system.web>
    
<httpModules>
  
<add name= "BasicAuthModule" 
      type
="HttpHandlers.BasicAuth,WebStore" />
    
</httpModules>
  
</system.web>
</configuration>

注意,你需要指定一個(gè)類(lèi)型全名,還有一個(gè)程序集的名字.
 
Modules允許你看到每一個(gè)請求并且基于觸發(fā)事件形式的執行動(dòng)作。Module非常適于修改request或者response的內容,用以提供定制的身份驗證或者為每一個(gè)請求執行預處理。很多的ASP.NET的特性,像身份驗證以及Sesion引擎都是通過(guò)HTTPModule來(lái)實(shí)現的。

雖然,HTTPModule感覺(jué)上像ISAPI Filter,他們可以查看每一個(gè)通過(guò)ASP.NET應用程序的請求,但是他們只是能夠監視映射到ASP.NET應程序或者ASP.NET虛擬目錄的請求。這樣,你可以查看ASPX文件,或者其他的映射到ASP.NET的擴展名。但是你不能監視一個(gè)標準的.HTM或者圖片文件,除非你把他們的擴展名顯式的映射到ASP.NET ISAPI dll,就像圖1顯式的。一個(gè)Module的經(jīng)常被用作,過(guò)濾指定文件夾下面的圖片,然后顯式一個(gè)‘SAMPLE’覆蓋在每一個(gè)圖片上面,通過(guò)使用GDI+。(譯者:水???)
 
實(shí)現一個(gè)HTTPModule非常的容易:你必須實(shí)現IHttpModule接口,這個(gè)接口僅僅有兩個(gè)方法,Init()和Dispose().這個(gè)時(shí)間參數是一個(gè)HttpApplication對象,通過(guò)他你可以訪(fǎng)問(wèn)Httpcontext對象,在這個(gè)方法中你可以接觸到HttpApplication的事件。舉個(gè)例子,如果你想附加AuthenticateRequest事件你可以像Listing5一樣。
Listing 5: 一個(gè)基礎的HTTP Module非常好實(shí)現

Code

記住,你的Module訪(fǎng)問(wèn)的是HttpContext對象,通過(guò)其就能獲得其他的管道對象,就如Response和Request,這樣你可以獲得輸入等等,但是記住,這些不一定在后面的事件鏈中還有效。
 
你可以附件多個(gè)事件在Init()方法中,這樣你就可以通過(guò)一個(gè)Module來(lái)管理不同的功能操作。然而,最好將不同的邏輯放在不同的類(lèi)中使得Module真正的模塊化。在你要實(shí)現的很多功能中,你需要附加到多個(gè)事件-舉個(gè)例子,一個(gè)日志filter需要早BeginRequest中記錄Request的開(kāi)始時(shí)間,而在EndRequest中記錄請求的完成時(shí)間。
 
注意HttpModules 和 HttpApplication 的事件events: Response.End() 或者 HttpApplication.CompleteRequest()將會(huì )切斷HttpApplication對象或者M(jìn)odule的事件鏈。See the sidebar “Watch out for Response.End() “ for more info.

HttpHandlers
Modules相當的底層而且,對應的是對應ASP.NET應用程序的每一個(gè)請求。HTTP Handler則更加側重于對于一個(gè)指定的請求的操作,通常一個(gè)頁(yè)面都被映射到Handler.
 
實(shí)現Http Handler要求非?;A,但是通過(guò)訪(fǎng)問(wèn)HttpContext對象可以獲得強大的功能。Http Handler通過(guò)實(shí)現一個(gè)非常簡(jiǎn)單的接口IHttpHandler來(lái)實(shí)現(或者其異步的版本的IHttpAsyncHandler),它僅僅包含了一的方法ProcessRequest()和一個(gè)IsReusagable屬性。關(guān)鍵的是,ProcessRequest()獲得了一個(gè)HttpContext對象的實(shí)例,這個(gè)方法負責處理Web請求,從開(kāi)始到結束。
 
一個(gè)簡(jiǎn)單的方法?非常的簡(jiǎn)單,對么?確實(shí),一個(gè)簡(jiǎn)單的接口,但是卻不是那么的簡(jiǎn)單!記得WebForm和WebService都是做為HTTPHandler的實(shí)現的,所以,很強大的功能封裝在這一個(gè)看似簡(jiǎn)單的接口中。關(guān)鍵點(diǎn)是,接觸到HTTP Handler的時(shí)候,ASP.NET的內置對象已經(jīng)為開(kāi)始處理請求而創(chuàng )建和設置好了。關(guān)鍵就是HttpContext對象,他提供了所有的請求相關(guān)的功能獲得輸入信息,輸出信息到Web服務(wù)器。
 
一個(gè)HTTPHandler所有的動(dòng)作發(fā)生都是通過(guò)調用這個(gè)單獨的ProcessRequest().這個(gè)可以簡(jiǎn)單的像:

public void ProcessRequest(HttpContext context)
{
context.Response.Write(
"Hello World");
}

也可以完全實(shí)現一個(gè)象WebForm Page引擎,可以輸出復雜格式HTML模板。這點(diǎn)完全取決與你的決定,你到底如何用這個(gè)簡(jiǎn)單,卻有強大的接口!
 
因為你可以使用Context對象,你可以獲得Request,Response,Session和Cache對象,這樣你有了所有的ASP.NET請求的特性, 你可以找到用戶(hù)提交的內容,也可以設置返回客戶(hù)端的內容。記住Context對象,他是你的朋友,在這個(gè)ASP.NET請求的生命周期中!
 
Handler的關(guān)鍵性的操作應帶是最終的把output輸出結果到Response對象,或者更具體的說(shuō)是Response對象的OutputStream。這個(gè)output返回客戶(hù)端的信息。在背后,ISAPIWorkerRequest負責將OutputStream返回到ISAPI ecb.WriteClient方法,執行了IIS輸出的過(guò)程。


圖 7 – ASP.NET請求管道流程通過(guò)一系列事件接口,提供了很大的靈活性。Application扮演了一個(gè)宿主容器的角色,它加載了Web應用程序,并且隨著(zhù)請求的進(jìn)入和在管道中的傳遞而觸發(fā)事件。每一個(gè)請求都是通過(guò)相同的路徑,通過(guò)HTTP Filters和設置了的Modules。Filters能夠檢測通過(guò)管道的每一個(gè)請求,而Handlers允許實(shí)現用用程序的邏輯和接口,就像WebForm和WebService。為了提供應用程序的輸入和輸出Context在整個(gè)過(guò)程提供了請求的相關(guān)信息。
 
WebForm在這個(gè)基礎框架上面,通過(guò)實(shí)現一個(gè)HTTPHandler以及更高層的接口,然而最終,Wenforms的Render()方法簡(jiǎn)單的使用一個(gè)HtmlTextWriter對象將其最終的輸出結果寫(xiě)入到context.Response.OutputStream。這樣,最終,一個(gè)高層的工具,像WebForms僅僅是一個(gè)Request和Response對象的高層的抽象。
 
你可能想知道,這點(diǎn)上,你是否需要處理HTTPHandler。畢竟,WebForm提供了簡(jiǎn)單的可訪(fǎng)問(wèn)的HTTPHandler實(shí)現,那么我們?yōu)槭裁匆艞夁@個(gè)靈活性而不厭其煩的做一些底層的事情呢?
 
WebForm對于生成復雜的HTML頁(yè)面和需要圖形布局工具,模板化頁(yè)面的商業(yè)邏輯非常的好。但是,WebForm執行了很多的增加消耗的任務(wù)。如果你僅僅想在系統中讀取一個(gè)文件,并將其返回,那么你可以跳過(guò)Web Form page框架,直接處理文件。如果你做的事情像從數據庫提供圖片,你也不需要Page框架—你不需要模板,而且沒(méi)有一個(gè)UI。沒(méi)有理由創(chuàng )建一個(gè)頁(yè)面對象和Seesion并且處理頁(yè)面級別的事件.

所以handlers更加高效。Handler也可以完成WebForm不能完成的任務(wù)。例如,他能夠處理一個(gè)請求,不需要磁盤(pán)上有物理文件。 做這個(gè),你需要在圖1中的應用程序擴展對話(huà)框中。
關(guān)閉“檢查文件是否存在”選項。
 
對于內容提供者是通用的,就像動(dòng)態(tài)圖片處理,XML服務(wù)器,Url重定向提供構造的Url,下載管理等等,這些都不是適合Wenform引擎。
對你來(lái)說(shuō),我介紹的足夠了么?
恩,我們這里已經(jīng)介紹了處理整個(gè)請求的過(guò)程。有很多的底層信息,我沒(méi)有仔細的講HTTPHandler和HTTPModule具體工作細節。挖掘這些信息需要一些時(shí)間,在理解ASP.NET怎樣工作上面,希望能給你和我自己一樣的滿(mǎn)意程度。
 
在結束之前,讓我們簡(jiǎn)短的回顧一下從IIS到handler的事件序列:
•IIS獲得請求
•檢測腳本映射,映射到ASP.NET_isapi.dll
•觸發(fā)工作進(jìn)程(ASP.NET_wp.exe 在 IIS5 或者 w3wp.exe 在 IIS6)
•.NET運行時(shí)加載
•IsapiRuntime.ProcessRequest()通過(guò)非托管代碼調用
•IsapiWorkerRequest created once per request
•IsapiWorkerRequest 每一次請求創(chuàng )建一次
•HttpRuntime.ProcessRequest() called with Worker Request
•通過(guò)傳進(jìn)Work Request, HttpContext對象被創(chuàng )建
•HttpApplication.GetApplicationInstance() called with Context to retrieve instance from pool
•HttpApplication.Init() 調用,并且啟動(dòng)管道事件序列,附加Modules和Handler
•被調用,開(kāi)始處理進(jìn)請求
•管道事件觸發(fā)
•Handlers被調用,并且ProcessRequest 方法執行
•控件返回管道并且發(fā)送請求事件觸發(fā)
 
通過(guò)這個(gè)簡(jiǎn)單的列表,把這些是如何組合起來(lái)的記住會(huì )更容易。我不時(shí)的來(lái)看它來(lái)記憶?,F在,我們回到工作上,繼續做一些不抽象的…
盡管,這里我說(shuō)的是基于A(yíng)SP.NET1.1,但是ASP.NET2.0中,并沒(méi)有改變這些底層的處理過(guò)程。
非常感謝微軟的Mike Volodarsky來(lái)審閱這篇文章,并且提了一些附件的提示并且 Michele Leroux Bustamante提供了ASP.NET管道請求基礎信息。


本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Asp.net MVC項目的部署(一):IIS以及Asp.net與IIS相關(guān)的部分
[讀書(shū)筆記](méi)[深入剖析ASP.NET組件設計]一書(shū)第三章關(guān)于A(yíng)SP.NET運行原理講述的補...
ASP.NET頁(yè)面與IIS底層交互和工作原理詳解
ASP.NET底層的初步認識與理解
ASP.NET網(wǎng)頁(yè)請求以及處理全過(guò)程(反編譯工具查看源代碼)
ASP.NET必須知道的:HttpModule,HttpHandler-程序開(kāi)發(fā)-紅黑聯(lián)盟
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久