ASP.NET MVC 是建立在 ASP.NET 平臺(tái)上基于 MVC 模式的 Web 應(yīng)用框架,深刻理解 ASP.NET MVC 的前提是對(duì) ASP.NET 管道式設(shè)計(jì)具有深刻的認(rèn)識(shí)君躺。由于 ASP.NET Web 應(yīng)用大都寄宿于 IIS 上峭判,將兩者結(jié)合起來(lái)了解在 IIS 和 ASP.NET 管道中是如何流動(dòng)的。
IIS5.x與ASP.NET
IIS5.x 是如何處理基于 ASP.NET 資源(如.aspx
棕叫、.asmx
...)請(qǐng)求的呢林螃?
IIS5.x運(yùn)行在進(jìn)程 InetInfo.exe
中,該進(jìn)程寄存著一個(gè)名為 World Wide Web Publishing Service(簡(jiǎn)稱W3SVC)的 Windows 服務(wù)俺泣。W3SVC 主要負(fù)責(zé) HTTP 請(qǐng)求的監(jiān)聽(tīng)疗认、激活、管理工作進(jìn)程伏钠、加載配置(從 Metabase 中加載相關(guān)配置信息)等横漏。
當(dāng)檢測(cè)到某個(gè) HTTP 請(qǐng)求時(shí),IIS 先根據(jù)擴(kuò)展名判斷請(qǐng)求的是靜態(tài)資源還是動(dòng)態(tài)資源贝润。對(duì)于靜態(tài)資源 IIS 會(huì)將文件內(nèi)容直接響應(yīng)給客戶端绊茧,對(duì)于動(dòng)態(tài)資源則通過(guò)擴(kuò)展名從 IIS 的腳本映射(Script Map)中找到相應(yīng)的ISAPI 動(dòng)態(tài)鏈接庫(kù)(Dynamic Link Library, DLL)打掘。
ISAPI(Internet Server Application Programming Interface)是一套本地的(Native)Win32 API华畏,是 IIS 和其他動(dòng)態(tài) Web 應(yīng)用或平臺(tái)之間的紐帶鹏秋。
ISAPI 定義在一個(gè)動(dòng)態(tài)鏈接庫(kù)(DLL)文件中, ASP.NET ISAPI 對(duì)應(yīng)的 DLL 文件名稱為 aspnet_isapi.dll
亡笑,位于 %windir%\Microsoft.NET\Framework\{version no}\
中侣夷。
ISAPI 支持 ISAPI 擴(kuò)展(ISAPI Extension)和 ISAPI 篩選(ISAPI Filter),前者是真正處理 HTTP 請(qǐng)求的接口仑乌,后者則可以在 HTTP 請(qǐng)求真正被處理之前查看百拓、修改、轉(zhuǎn)發(fā)晰甚、拒絕請(qǐng)求衙传,比如 IIS 可利用 ISAPI 篩選進(jìn)行請(qǐng)求的驗(yàn)證。
若請(qǐng)求的是一個(gè)基于 ASP.NET 的資源類型厕九,如.aspx
蓖捶、.asmx
、.svc
等扁远,aspnet_isapi.dll
會(huì)被加載俊鱼,ASP.NET ISAPI 隨后會(huì)創(chuàng)建 ASP.NET 的工作進(jìn)程(若該進(jìn)程尚未啟動(dòng))。對(duì)于 IIS5.x 來(lái)說(shuō)畅买,該工作進(jìn)程為 aspnet.exe
并闲。IIS 進(jìn)程與工作進(jìn)程之間通過(guò)命名管道(Named Pipes)進(jìn)行通信。
在工作進(jìn)程初始化過(guò)程中谷羞,.NET 運(yùn)行時(shí)(CLR)會(huì)被加載以構(gòu)建一個(gè)托管的環(huán)境帝火。對(duì)于某個(gè) Web 應(yīng)用的初次請(qǐng)求,CLR 會(huì)被其創(chuàng)建一個(gè)應(yīng)用程序域(Application Domain)洒宝。
在應(yīng)用程序域中购公,HTTP 運(yùn)行時(shí)(HTTP Runtime)被加載并用以創(chuàng)建相應(yīng)的應(yīng)用。寄存于 IIS5.x 的所有Web應(yīng)用都運(yùn)行在同一個(gè)進(jìn)程(工作進(jìn)程 aspnet_wp.exe
)的不同應(yīng)用程序域中雁歌。
IIS6.0 與 ASP.NET
IIS5.x存在兩個(gè)方面的不足:
- ISAPI動(dòng)態(tài)鏈接庫(kù)被加載到
InetInfo.exe
進(jìn)程中宏浩,它和工作進(jìn)程之間是一種典型的跨進(jìn)程通信方式,盡管采用命名管道靠瞎,仍會(huì)帶來(lái)性能瓶頸比庄。
解決方案:IIS6.0將ISAPI動(dòng)態(tài)鏈接庫(kù)直接加載到工作進(jìn)程中
- ASP.NET 應(yīng)用運(yùn)行在相同進(jìn)程
aspnet_wp.exe
的不同程序域中,基于應(yīng)用程序域的隔離不能從根本上解決一個(gè)應(yīng)用程序?qū)α硪粋€(gè)程序的影響乏盐,需不同的Web應(yīng)用運(yùn)行在不同的進(jìn)程中佳窑。
解決方案:IIS6.0 加入了應(yīng)用程序池 Application Pool 的機(jī)制,為一個(gè)或多個(gè) Web 應(yīng)用創(chuàng)建一個(gè)應(yīng)用程序池父能,每個(gè)應(yīng)用程序池對(duì)應(yīng)一個(gè)獨(dú)立的工作進(jìn)程 w3wp.exe
神凑,所以運(yùn)行在不同應(yīng)用程序池中的 Web 應(yīng)用提供基于進(jìn)程級(jí)別的隔離機(jī)制。
HTTP.SYS
IIS6.0 中最重要的一點(diǎn)是創(chuàng)建了一個(gè)名為 HTTP.SYS 的 HTTP 監(jiān)聽(tīng)器,HTTP.SYS 以驅(qū)動(dòng)程序的形式運(yùn)行在Windows 的內(nèi)核模式 Kernal Mode下溉委,它是 Windows TCP/IP 網(wǎng)絡(luò)子系統(tǒng)的一部分鹃唯,從結(jié)構(gòu)上看它屬于 TCP 之上的一個(gè)網(wǎng)絡(luò)驅(qū)動(dòng)程序。
嚴(yán)格地說(shuō)瓣喊,HTTP.SYS 已經(jīng)不屬于 IIS 的范疇了坡慌,所以 HTTP.SYS 的配置信息也沒(méi)有保存在 IIS 的元數(shù)據(jù)庫(kù)Metabase,而是定義在注冊(cè)表中藻三。HTTP.SYS 的注冊(cè)表項(xiàng)的路徑為HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/HTTP
洪橘。
HTTP.SYS能夠帶來(lái)如下好處:
- 持續(xù)監(jiān)聽(tīng)
由于 HTTP.SYS 是一個(gè)網(wǎng)路驅(qū)動(dòng)程序,始終處于運(yùn)行狀態(tài)棵帽,所以對(duì)于用戶會(huì)的 HTTP 請(qǐng)求能夠及時(shí)作出反應(yīng)熄求。
- 穩(wěn)定性
HTTP.SYS 運(yùn)行在操作系統(tǒng)內(nèi)核模式下,并不執(zhí)行任何用戶代碼逗概,其本身不會(huì)受到 Web應(yīng)用抡四、工作進(jìn)程、IIS進(jìn)程的影響仗谆。
- 內(nèi)核模式下的數(shù)據(jù)緩存
如果某個(gè)資源被頻繁請(qǐng)求,HTTP.SYS 會(huì)把響應(yīng)的內(nèi)容進(jìn)行緩存淑履,緩存的內(nèi)容可直接響應(yīng)后續(xù)的請(qǐng)求隶垮。由于這是基于內(nèi)核模式的緩存,不存在內(nèi)核模式和用戶模式的切換秘噪,響應(yīng)速度得到極大的改進(jìn)狸吞。
IIS6.0結(jié)構(gòu)
與 IIS5.x 不同,W3SVC 在 IIS6.0 中從 InetInfo.exe
進(jìn)程脫離出來(lái)指煎,對(duì)于 IIS6.0 來(lái)說(shuō)蹋偏,InetInfo.exe
基本上可以看做單純的 IIS 管理進(jìn)程,運(yùn)行在另一個(gè)進(jìn)程 SvcHost.exe
中至壤。不過(guò) W3SVC 的基本功能并沒(méi)有發(fā)生變化威始,只是在功能的實(shí)現(xiàn)上作出相應(yīng)的改進(jìn)。與 IIS5.x 一樣像街,元數(shù)據(jù)庫(kù) Metabase 依然存在于InetInfo.exe
進(jìn)程中黎棠。
IIS6.0處理HTTP請(qǐng)求的流程
當(dāng)監(jiān)聽(tīng)到HTTP請(qǐng)求時(shí),HTTP.SYS 將其分發(fā)給 W3SVC镰绎,W3SVC 解析出請(qǐng)求的 URL ,并根據(jù)從 Metabase 獲取的 URL 與 Web 應(yīng)用之間的映射關(guān)系得到目標(biāo)應(yīng)用脓斩,進(jìn)而得到目標(biāo)應(yīng)用運(yùn)行的應(yīng)用程序池或工作進(jìn)程。如果工作進(jìn)程不存在或尚未創(chuàng)建或被回收畴栖,它為請(qǐng)求創(chuàng)建新的工作進(jìn)程随静。在工作進(jìn)程的初始化過(guò)程中,相應(yīng)的 ISAPI 動(dòng)態(tài)鏈接庫(kù)被加載吗讶,對(duì)于 ASP.NET 應(yīng)用來(lái)說(shuō)燎猛,被加載的 ISAPI.dll
為 aspnet_isapi.dll
恋捆。ASP.NET ISAPI 負(fù)責(zé)進(jìn)行 CLR 的加載、應(yīng)用程序域的創(chuàng)建和 Web 應(yīng)用的初始化等操作扛门。
IIS7.0與ASP.NET
IIS7.0在請(qǐng)求的監(jiān)聽(tīng)和分發(fā)機(jī)制上進(jìn)行了革新鸠信,體現(xiàn)在引入Windows進(jìn)程激活服務(wù)(Windows Process Activation Service, WAS),分流了原來(lái)IIS6.0中W3SVC承載的部分功能论寨。
IIS6.0中的W3SVC主要承載著如下三個(gè)功能:
- HTTP請(qǐng)求接收:接收HTTP.SYS監(jiān)聽(tīng)到的HTTP請(qǐng)求
- 配置管理:從元數(shù)據(jù)Metabase中加載配置信息對(duì)相關(guān)組件進(jìn)行配置
- 進(jìn)程管理:創(chuàng)建星立、回收、監(jiān)控工作進(jìn)程
IIS7.0將后兩組功能實(shí)現(xiàn)到了WAS中葬凳,但接收HTTP請(qǐng)求的任務(wù)依然落在W3SVC上绰垂。WAS的引入為IIS7.0提供了對(duì)非HTTP協(xié)議的支持,通過(guò)監(jiān)聽(tīng)適配器接口 Listener Adapter Interface抽象出針對(duì)不同協(xié)議的監(jiān)聽(tīng)器火焰。具體來(lái)說(shuō)或劲装,除了專門用于監(jiān)聽(tīng)HTTP請(qǐng)求的HTTP.SYS之外,WAS利用TCP監(jiān)聽(tīng)器昌简、命名管道監(jiān)聽(tīng)器和MSMQ監(jiān)聽(tīng)器提供基于TCP占业、命名管道、MSMQ傳輸協(xié)議的監(jiān)聽(tīng)支持纯赎。
與此3種監(jiān)聽(tīng)器相對(duì)應(yīng)的是3種監(jiān)聽(tīng)適配器谦疾,它們提供監(jiān)聽(tīng)器與WAS中的監(jiān)聽(tīng)適配器接口之間的適配,從這個(gè)意義上講犬金,IIS7.0中的W3SVC相當(dāng)于HTTP.SYS的監(jiān)聽(tīng)適配器念恍。這3種非HTTP監(jiān)聽(tīng)器和監(jiān)聽(tīng)適配器定義在程序集 SMSvcHost.exe 中⊥砬辏可在目錄%windir%\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\
中找到峰伙。
從程序集所在的目錄名稱可以看出,這3種監(jiān)聽(tīng)器/監(jiān)聽(tīng)適配器是為WCF設(shè)計(jì)的该默,它們以Windows服務(wù)的形式進(jìn)行工作瞳氓。雖然定義在一個(gè)程序集中。但依然可通過(guò)服務(wù)工作管理器對(duì)其進(jìn)行單獨(dú)的啟動(dòng)权均、終止顿膨、配置∵瓷蓿總的來(lái)說(shuō)恋沃,SMSvcHost.exe提供了4個(gè)重要的Windows Service。
- NetTcpPortSharing
為WCF提供TCP端口共享必指,即同一個(gè)監(jiān)聽(tīng)端口被多個(gè)進(jìn)程共享囊咏。 - NetTcpActivator
為WAS提供基于TCP的激活請(qǐng)求,包含TCP監(jiān)聽(tīng)器和對(duì)應(yīng)的監(jiān)聽(tīng)適配器。 - NetPipeActivator
為WAS提供基于命名管道的激活請(qǐng)求梅割,包含命名管道和對(duì)應(yīng)的監(jiān)聽(tīng)適配器霜第。 - NetMsmqActivator
為WAS提供基于MSMQ的激活請(qǐng)求,包含MSMQ監(jiān)聽(tīng)器和對(duì)應(yīng)的監(jiān)聽(tīng)適配器户辞。
IIS7.0架構(gòu)
無(wú)論是從W3SVC接收到的HTTP請(qǐng)求泌类,還是通過(guò)WCF提供的監(jiān)聽(tīng)適配器接收到的針對(duì)其他傳輸協(xié)議的請(qǐng)求,最終都胡被傳遞到WAS底燎。如果相應(yīng)的工作進(jìn)程刃榨,針對(duì)單個(gè)應(yīng)用程序池尚未創(chuàng)建,則WAS會(huì)創(chuàng)建工作進(jìn)程双仍。WAS在進(jìn)行請(qǐng)求處理過(guò)程中通過(guò)內(nèi)置的配置管理模塊加載相關(guān)的配置信息枢希,并對(duì)相關(guān)的組件進(jìn)行配置。
與IIS5.x和IIS6.0基于Metabase的配置信息存儲(chǔ)不同的是朱沃,IIS7.0大多將配置信息存放在XML形式的配置文件中苞轿,基本的配置存放在 applicationHost.config 中。
API.NET 集成
從IIS5.x和IIS6.0中不難發(fā)現(xiàn)逗物,IIS與ASP.NET是兩個(gè)獨(dú)立的管道 Pipeline搬卒。在各自管轄范圍內(nèi),各自具有自己的一套機(jī)制對(duì)HTTP請(qǐng)求進(jìn)行處理翎卓。兩個(gè)管道通過(guò)ISAPI實(shí)現(xiàn)連通秀睛。IIS是第一道屏障,當(dāng)對(duì)HTTP請(qǐng)求進(jìn)行必要的前期處理莲祸,如身份認(rèn)證等。IIS通過(guò)ISAPI將請(qǐng)求分發(fā)給ASP.NET管道椭迎。當(dāng)ASP.NET在自身管道范圍內(nèi)完成對(duì)HTTP請(qǐng)求的處理時(shí)锐帜,處理后的結(jié)果再返回到IIS,IIS對(duì)其進(jìn)行后期處理畜号,如日志記錄缴阎、壓縮等。之后生成HTTP回復(fù)對(duì)請(qǐng)求予以響應(yīng)简软。
從另一個(gè)角度講蛮拔,IIS運(yùn)行在非托管的環(huán)境中,而ASP.NET管道則是托管的痹升,所以說(shuō)ISAPI是連接非托管環(huán)境和托管環(huán)境的紐帶建炫。IIS5.x和IIS6.0把兩個(gè)管道進(jìn)行隔離帶來(lái)的局限的不足是:
- 相同操作的重復(fù)執(zhí)行
IIS和ASP.NET之間具有一些重復(fù)的操作,如身份驗(yàn)證疼蛾。
- 動(dòng)態(tài)文件與靜態(tài)文件處理的不一致
因?yàn)橹挥谢贏SP.NET 動(dòng)態(tài)文件的HTTP請(qǐng)求才能通過(guò)ASP.NET ISAPI進(jìn)入ASP.NET管道肛跌,對(duì)于靜態(tài)文件的請(qǐng)求則由IIS直接響應(yīng),那么ASP.NET管道中的一些功能將不能作用域這些基于靜態(tài)文件的請(qǐng)求,比如通過(guò)Forms認(rèn)證應(yīng)用于基于圖片文件的請(qǐng)求就做不到衍慎。
- IIS難以擴(kuò)展
對(duì)于IIS的擴(kuò)展基本上提現(xiàn)在自定義ISAPI转唉,對(duì)于大部分人來(lái)說(shuō),這不是一件容易的事情稳捆,因?yàn)镮SAPI是基于Win32的非托管的API赠法,并非一種面向應(yīng)用的編程接口。通常希望的是諸如定義ASP.NET的HttpModule和HttpHandler一樣乔夯,托管代理的方式來(lái)擴(kuò)展IIS砖织。
對(duì)于Windows平臺(tái)下的IIS來(lái)講,ASP.NET無(wú)疑是一等公民驯嘱,IIS7.0中實(shí)現(xiàn)了兩者的集成镶苞,通過(guò)集成可獲得如下好處:
- 允許通過(guò)本地代碼Native Code和托管代碼Managed Code兩種方式定義IIS Module
這些IIS Module注冊(cè)到IIS中形成一個(gè)通用的請(qǐng)求處理管道,由IIS Module組成的這個(gè)管道能夠處理所有的請(qǐng)求鞠评,無(wú)論請(qǐng)求基于怎樣的資源類型茂蚓。例如,可將FormAuthenticationModule提供的Forms認(rèn)證應(yīng)用到基于 .aspx剃幌、CGI和靜態(tài)文件的請(qǐng)求聋涨。
- 將ASP.NET提供的一些強(qiáng)大的功能應(yīng)用到原來(lái)難以企及的地方
比如將ASP.NET的URL重寫(xiě)功能置于身份驗(yàn)證之前
- 采用相同的方式去實(shí)現(xiàn)、配置负乡、檢測(cè)和支持一些服務(wù)器特性 Feature
比如Module牍白、Handler映射、定制錯(cuò)誤配置 Custom Error Configuration 等
ASP.NET 管道
以 IIS6.0為例抖棘,它的工作進(jìn)程 w3wp.exe
中會(huì)利用 aspnet_isapi.dll
加載 .NET 運(yùn)行時(shí)(如果 .NET 運(yùn)行時(shí)尚未加載)茂腥。IIS6.0引入了應(yīng)用程序池的概念,一個(gè)工作進(jìn)程對(duì)應(yīng)著一個(gè)應(yīng)用程序池切省。一個(gè)應(yīng)用程序池可以承載一個(gè)或多個(gè)Web應(yīng)用最岗,每個(gè)Web應(yīng)用映射到一個(gè)IIS虛擬目錄,與IIS5.x一樣朝捆,每個(gè)Web應(yīng)用運(yùn)行在各自的應(yīng)用程序域中般渡。
如果HTTP.SYS接收到的HTTP請(qǐng)求是對(duì)該 Web 應(yīng)用的第一次訪問(wèn),在成功加載運(yùn)行使之后芙盘,IIS會(huì)通過(guò) AppDomainFactory 為該Web應(yīng)用創(chuàng)建一個(gè)應(yīng)用程序域驯用。隨后一個(gè)特殊的運(yùn)行時(shí) IsapiRuntime 被加載。IsapiRuntime 定義在程序集 System.Web.dll
中儒老,對(duì)應(yīng)的命名空間為System.Web.Hosting
蝴乔, 被加載的 IsapiRuntime 會(huì)接管該HTTP請(qǐng)求。
接管 HTTP 請(qǐng)求的 IsapiRuntime 會(huì)首先創(chuàng)建一個(gè) IsapiWorkerRequest 對(duì)象來(lái)封裝當(dāng)前的HTTP請(qǐng)求驮樊,隨后將次對(duì)象傳遞給 ASP.NET 運(yùn)行時(shí) HttpRuntime淘这。從此時(shí)起剥扣, HTTP請(qǐng)求正式進(jìn)入了ASP.NET管道。HttpRuntime會(huì)根據(jù) IsapiWorkerRequest 對(duì)象創(chuàng)建用于表示當(dāng)前HTTP請(qǐng)求的上下文 Context 對(duì)象 HttpContext铝穷。
隨著 HttpContext 的創(chuàng)建钠怯,HttpRuntime 會(huì)利用 HttpApplicationFactory 創(chuàng)建新的或獲取現(xiàn)有的 HttpApplication 對(duì)象。實(shí)際上 ASP.NET 維護(hù)著一個(gè) HttpApplication 對(duì)象池曙聂, HttpApplicationFactory 從池中選取可用的 HttpApplication 用于處理 HTTP 請(qǐng)求晦炊,處理完畢后將其釋放到對(duì)象池中。HttpApplication 負(fù)責(zé)處理當(dāng)前的 HTTP 請(qǐng)求宁脊。
在 HttpApplication 初始化過(guò)程中断国,ASP.NET 會(huì)根據(jù)配置文件加載并初始化注冊(cè)的 HttpModule 對(duì)象。對(duì)于 HttpApplication 來(lái)說(shuō)榆苞,在它處理HTTP請(qǐng)求的不同階段會(huì)觸發(fā)不同的事件 Event稳衬,而HttpModule的意義在于通過(guò)注冊(cè)HttpApplication的相應(yīng)事件,將所需的操作注入整個(gè)HTTP請(qǐng)求的處理流程坐漏。ASP.NET的很多功能都是通過(guò)相應(yīng)的HttpModule實(shí)現(xiàn)的薄疚。
最終完成對(duì)HTTP請(qǐng)求的處理實(shí)現(xiàn)在HttpHandler
中,不同的資源類型對(duì)應(yīng)著不同類型的HttpHandler
赊琳。比如.aspx
頁(yè)面對(duì)應(yīng)的HttpHandler類型為System.Web.UI.Page
街夭,WCF的.svc
文件對(duì)應(yīng)的HttpHandler類型為System.ServiceModel.Activation.HttpHandler
。
HttpApplication
HttpApplication 是整個(gè) ASP.NET 基礎(chǔ)架構(gòu)的核心躏筏,負(fù)責(zé)處理分發(fā)給它的HTTP請(qǐng)求板丽。由于一個(gè)HttpApplication對(duì)象在某個(gè)時(shí)刻只能處理一個(gè)請(qǐng)求,只有完成對(duì)某個(gè)請(qǐng)求的處理后才能用于后續(xù)請(qǐng)求的處理趁尼,所以ASP.NET采用對(duì)象池的機(jī)制來(lái)創(chuàng)建或獲取 HttpApplication 對(duì)象埃碱。
當(dāng)?shù)谝粋€(gè)請(qǐng)求抵達(dá)時(shí),ASP.NET會(huì)一次創(chuàng)建多個(gè)HttpApplication對(duì)象酥泞,并將其置于池中乃正,然后選擇其中一個(gè)對(duì)象來(lái)處理該請(qǐng)求。處理完畢后婶博,HttpApplication不會(huì)被回收,而是釋放到池中荧飞。對(duì)于后續(xù)的請(qǐng)求凡人,空閑的 HttpApplication 對(duì)象會(huì)從池中取出。如果池中所有的 HttpApplication 對(duì)象都處于繁忙的狀態(tài)叹阔,在沒(méi)有超出 HttpApplication 池最大容量的情況下挠轴,ASP.NET 會(huì)創(chuàng)建新的HttpApplication對(duì)象,否則將請(qǐng)求放入隊(duì)列等待現(xiàn)有HttpApplication的釋放耳幢。
HttpApplication 處理請(qǐng)求的整個(gè)生命周期是一個(gè)相對(duì)復(fù)雜的過(guò)程岸晦,在該過(guò)程的不同階段會(huì)觸發(fā)相應(yīng)的事件欧啤。可注冊(cè)相應(yīng)的事件启上,將處理邏輯注入到HttpApplication處理請(qǐng)求的某個(gè)階段邢隧。
HttpApplication在處理每個(gè)請(qǐng)求時(shí)觸發(fā)的事件
BeginRequest
HTTP管道開(kāi)始處理請(qǐng)求時(shí),會(huì)觸發(fā)BeginRequest
事件冈在。AuthenticateRequest, PostAuthenticateRequest
ASP.NET 先后觸發(fā)這兩個(gè)事件倒慧,使安全模塊對(duì)請(qǐng)求進(jìn)行身份驗(yàn)證。AuthorizeRequest, PostAuthorizeRequest
ASP.NET先后觸發(fā)這兩個(gè)事件包券,使安全模塊對(duì)請(qǐng)求進(jìn)行授權(quán)纫谅。ResolveRequestCache, PostResolveRequestCache
ASP.NET 先后觸發(fā)這兩個(gè)事件,以使緩存模塊利用緩存的內(nèi)容對(duì)請(qǐng)求直接進(jìn)行響應(yīng)(緩存模塊可將響應(yīng)內(nèi)容進(jìn)行緩存溅固,對(duì)于后續(xù)的請(qǐng)求付秕,直接將緩存的內(nèi)容返回,從而提高響應(yīng)能力侍郭。)PostMapRequestHandler
對(duì)于訪問(wèn)不同資源類型询吴,ASP.NET具有不同的HttpHandler對(duì)其進(jìn)行處理,對(duì)于每個(gè)請(qǐng)求励幼,ASP.NET會(huì)通過(guò)擴(kuò)展名選擇匹配響應(yīng)的HttpHandler類型汰寓,成功匹配后,該事件被觸發(fā)苹粟。AcquireRequestState, PostAcquestRequestState
ASP.NET先后觸發(fā)這兩個(gè)事件有滑,使?fàn)顟B(tài)管理模塊獲取基于當(dāng)前請(qǐng)求相應(yīng)的狀態(tài),如SessionState嵌削。PreRequestHandlerExecute毛好、PostRequestHandlerExecute
ASP.NET 最終通過(guò)與請(qǐng)求資源類型相對(duì)應(yīng)的 HttpHandler 實(shí)現(xiàn)對(duì)請(qǐng)求的處理,在實(shí)行 HttpHandler 前后苛秕,這兩個(gè)事件被先后觸發(fā)肌访。ReleaseRequestState、PostReleaseRequestState
ASP.NET 先后觸發(fā)這兩個(gè)事件艇劫,使?fàn)顟B(tài)管理模塊釋放基于當(dāng)前請(qǐng)求響應(yīng)的狀態(tài)吼驶。UpdateRequesetCache、PostUpdateRequestCache
ASP.NET先后觸發(fā)這兩個(gè)事件店煞,以使緩存模塊將HttpHandler處理請(qǐng)求得到的內(nèi)容得以保存到輸出緩存中蟹演。LogRequest、PostLogRequest
ASP.NET先后觸發(fā)這兩個(gè)事件為當(dāng)前請(qǐng)求進(jìn)行日志記錄EndRequest 整個(gè)請(qǐng)求處理完成后顷蟀,EndRequest事件會(huì)觸發(fā)酒请。
對(duì)于一個(gè)ASP.NET應(yīng)用來(lái)說(shuō),HttpApplication派生于Global.asax文件鸣个,通過(guò)創(chuàng)建Global.asax文件對(duì)HttpApplication的請(qǐng)求處理行為進(jìn)行定制羞反。Global.asax采用一種很直接的方式實(shí)現(xiàn)了這樣的功能布朦,這種方式不是方法重寫(xiě)或事件注冊(cè),而是直接采用方法名匹配昼窗。在Global.asax中按照“Application_{Event Name}”的命名規(guī)則進(jìn)行事件注冊(cè)是趴。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
namespace Huyoo.Backend
{
// 注意: 有關(guān)啟用 IIS6 或 IIS7 經(jīng)典模式的說(shuō)明,
// 請(qǐng)?jiān)L問(wèn) http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
}
HttpModule
ASP.NET擁有一個(gè)具有高度的可擴(kuò)展的引擎膏秫,能處理不同資源類型的請(qǐng)求右遭,HttpModule是功不可沒(méi)的。
當(dāng)請(qǐng)求轉(zhuǎn)入ASP.NET管道時(shí)缤削,最終負(fù)責(zé)處理該請(qǐng)求的是與請(qǐng)求資源類型相匹配的HttpHandler對(duì)象窘哈,但是在HttpHandler正式工作之前。ASP.NET會(huì)先加載并初始化所有配置的HttpModule對(duì)象亭敢。HttpModule在初始化過(guò)程中滚婉,會(huì)將一些回調(diào)操作注冊(cè)到HttpApplication相應(yīng)的事件中。在HttpApplication請(qǐng)求處理生命周期中的某個(gè)階段帅刀,相應(yīng)的事件會(huì)被觸發(fā)让腹,通過(guò)HttpModule注冊(cè)的事件處理程序也得以執(zhí)行。
所有的HttpModule都實(shí)現(xiàn)了具有如下定義的System.Web.IHttpModule
接口扣溺,其Init
方法實(shí)現(xiàn)了針對(duì)自身的初始化骇窍。該方法接受一個(gè)HttpApplication
對(duì)象,有了這個(gè)對(duì)象锥余,事件注冊(cè)就很容易了腹纳。
public interface IHttpModule
{
void Dispose();
void Init(HttpApplication context);
}
ASP.NET提供了很多基礎(chǔ)功能是通過(guò)相應(yīng)的HttpModule實(shí)現(xiàn)的。除了系統(tǒng)定義的HttpModule之外驱犹,可自定義HttpModule嘲恍,通過(guò) Web.config 可很容易地將其注冊(cè)到 Web 應(yīng)用中。
- OutputCacheModule
實(shí)現(xiàn)了輸出緩存(Output Caching)的功能 - SessionStateModule
在無(wú)狀態(tài)的HTTP協(xié)議上實(shí)現(xiàn)了基于會(huì)話Session的狀態(tài)保持 - WindowsAuthenticationModule + FormsAuthenticationModule + PassportAuthenticationModule
實(shí)現(xiàn)了Windows雄驹、Forms佃牛、Passport三種典型的身份認(rèn)證方式 - UrlAuthorizationModule + FileAuthorizationModule
實(shí)現(xiàn)了基于URL和文件ACL(Access Control List)的授權(quán)
HttpHandler
對(duì)于不同資源類型的請(qǐng)求,ASP.NET會(huì)加載不同的Handler來(lái)處理医舆,比如.aspx頁(yè)面與.asmx Web服務(wù)對(duì)應(yīng)的Handler是不同的俘侠。
所有的HttpHandler
都實(shí)現(xiàn)了具有如下定義的接口 System.Web.IHttpHandler
,定義其中的方法ProcessRequest
提供了處理請(qǐng)求的實(shí)現(xiàn)蔬将。
另一個(gè)代表異步版本的HttpHandler
的IHttpAsyncHandler
接口繼承自IHttpHandler
爷速,它通過(guò)調(diào)用BeginProcessRequest/EndProcessRequest
方法以異步的方式處理請(qǐng)求。
public interface IHttpHandler
{
void ProcessRequest(HttpContext context);
bool IsReusable{ get; }
}
public interface IHttpAsyncHandler:IHttpHandler
{
IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData);
void EndProcessRequest(IAsyncResult result);
}
某些 HttpHandler
具有一個(gè)與之相關(guān)的HttpHandlerFactory
娃胆,后者實(shí)現(xiàn)了具有如下定義的接口 System.Web.IHttpHandlerFactory
,定義其中的方法GetHandler
用于創(chuàng)建新的HttpHandler
或獲取已經(jīng)存在的HttpHandler
等曼。
public interface IHttpHandlerFactory
{
IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTransslated);
void ReleaseHandler(IHttpHandler handler);
}
HttpHandler和HttpHandlerFactory的類型都可以通過(guò)相同的方式配置到 Web.config中里烦。
在調(diào)用當(dāng)前HttpContext的RemapHandler方法時(shí)指定一個(gè)具體的HttpHandler對(duì)象凿蒜,是為了讓ASP.NET直接跳過(guò)默認(rèn)的HttpHandler映射操作。此外胁黑,由于這個(gè)默認(rèn)的HttpHandler映射發(fā)生在HttpApplication的PostMapRequestHandler事件觸發(fā)之前废封,所以只有在這之前調(diào)用RemapHandler方法才有意義。