Http請求的處理過程
Http請求首先到達Web Server,Web Server可以是IIS、Appache等,這些伺服器都可以有自己的具有一定介面的擴充來增強其功能,其中IIS使用ISAPI擴充來增強功能,Asp.net就是ISAPI擴充的一種。
IIS是使用被請求的資源的副檔名來決定使用哪個ISAPI擴充來處理該請求的,所以如果需要讓某一副檔名的資源被Asp.net處理,就需要在IIS裡配置該副檔名與c:/windows/microsoft.net/framework/v2.0.50727/aspnet_isapi.dll進行映射,還包括請求的類型(Get、Post等)。
Http請求會通過若干個HttpModules(其中一個是SessionStateModule,用於管理工作階段狀態)和一個HttpHandler來處理,具體的HttpHandler可以在Web.config裡配置,任何實現了IHttpHandler介面的類都可以在Web.config檔案裡配置為一個HttpHandler來處理Http請求,如果是用ashx檔案來實現則會自動設定,不需要在Web.config裡進行配置。
IHttpModule介面有兩個方法:Init()和Dispose(),HttpModule一般是採用在Init裡進行事件綁定的方式來處理HttpApplication的某個事件,典型應用有身分識別驗證AuthenticateRequest等。HttpHandler是可以配置成處理有特定副檔名資源的處理常式,它和Web Page有兩個區別,就是不用Response.ClearContent(),直接設定Response.ContentType並Write就可以了,可以使程式員專註於代碼邏輯的編寫,然後是在需要訪問Session的時候需要實現IRequiresSessionState介面。
如果有多個HttpModule裡都處理了Application_BeginRequest事件,則不一定每個都執行,因為當某一個執行Application_BeginRequest出現異常的時候,後面的幾個都不會再執行Application_BeginRequest,但是它們如果有Application_EndRequest就都會被執行,因為需要釋放資源。
IHttpHandler介面有兩個成員:IsReusable和ProcessRequest()。
IHttpHandlerFactory介面有兩個成員:GetHandler()和ReleaseHandler(),實現這個介面的類可以在Web.config裡配置成HttpHandler工廠,把HttpRequest路由到合適的Handler。
如果請求的資源是一個aspx頁,那麼先看該頁是否被編譯,如果沒有,則先編譯它,再用它的一個執行個體來處理請求。在編譯該頁之前,會先編譯top-level items,如App_GlobalResources、App_WebResources、Profile properties defined in the Web.config file、App_Code、Global.asax。當這些執行完,就會根據處理該請求的需要編譯Folders、Pages和其它需要的項目。
注意top-level items只會編譯一次,只有在它們依賴的東西如Web.config發生了改變的時候才重新編譯。
被編譯的Assembly會被Cache在Server,所以除了第一次請求會等較長的編譯時間外,以後的請求都會很快,當然也可以先行編譯,讓第一次請求也很快。
1.IIS是使用請求的副檔名來與ISAPI擴充進行映射的,這是可配置的。Asp.net就是ISAPI Extension的一種,能夠處理.aspx, .ascx, .ashx, and .asmx等。當需要某自訂副檔名的資源受Asp.net處理的時候就要映射一下副檔名和Aspnet_isapi.dll。
2.當第一次請求到來時,ApplicationManager會建立一個應用程式定義域Application Domain,應用程式定義域為全域變數提供應用程式之間的隔離,並可以使每個應用程式被單獨的卸載。在應用程式定義域裡,HostingEnvironment執行個體被建立,它提供對應用程式資訊的訪問,比如儲存應用程式的檔案夾名。
3.當Application Domain建立完成並且HostingEnvironment被執行個體化之後,Asp.net建立和初始化Core Object,比如HttpContext、HttpRequest、HttpResponse。HttpContext包含特定於當前應用程式請求的對象,比如HttpRequest、HttpResponse,HttpRequest包含有關當前請求的資訊,包括Cookie和瀏覽器資訊,HttpResponse包含發送到瀏覽器的回應,包括所有的呈現輸出和Cookie。
4.給Request指定Application對象。當所有的Core Objects被初始化之後,應用程式就開始於一個HttpApplication對象的建立,HttpApplication對象是Reusable的,即第一次請求的時候是建立,以後的請求都使用第一次建立的對象。當應用程式有Global.asax檔案時,Asp.net就會建立一個繼承於HttpApplication類的Global.asax執行個體,並使用這個衍生類別來處理應用程式。當Application類建立後,所有配置的HttpModules也都被建立,然後Application的Init()被調用。
HttpApplication對象的事件發生順序為:
首先會ValidateRequest,看是否有potentially malicious markup。
然後看Web.config檔案裡是否配置了UrlMappingsSection,有就執行Url Mapping。
最後執行下面的:
1.BeginRequest
2.AuthenticateRequest - PostAuthenticateRequest
4.AuthorizeRequest - PostAuthorizeRequest
6.ResolveRequestCache - PostResolveRequestCache
然後根據設定檔裡的副檔名與Handler的映射來選擇一個適合的Handler,或者根據HandlerFactory來選擇一個合適的Handler,去處理請求。如果請求的是一個WebPage,而該頁又需要被編譯,Asp.net就會在產生這個頁的執行個體之前編譯這個頁。
8.PostMapRequestHandler
9.AcquireRequestState - PostAcquireRequestState
11.PreRequestHandlerExecute
然後會調用調用適當HttpHandler類的ProcessRequest()方法,如果是非同步,則會調用BeginProcessRequest()方法。例如如果請求一個WebPage,則由該Page的一個執行個體來處理這個Request。
12. PostRequestHandlerExecute
13.ReleaseRequestState - PostReleaseRequestState
然後如果Filter屬性被定義了,就會執行ResponseFiltering。
15.UpdateRequestCache - PostUpdateRequestCache
17.LogRequest - PostLogRequest
19.EndRequest