ASP.NET的運行原理與運行機制 如何:為 IIS 7.0 配置


 

 ASP.NET的運行原理

 

 

  當一個HTTP請求到服務器並被IIS接收到之后,IIS首先通過客戶端請求的頁面類型為其加載相應的.dll文件,然后在處理過程中將這條請求發送給能夠處理這個請求的模塊。在ASP.NET 3.5中,這個模塊叫做HttpHandler(HTTP處理程序組件),之所以.aspx文件可以被服務器處理,就是因為在服務器端有默認的HttpHandler專門處理.aspx文件。IIS在將這條請求發送給能夠處理這個請求的模塊之前,還需要經過一些HttpModule的處理,這些都是系統默認的Modules(用於獲取當前應用程序的模塊集合),在這個HTTP請求傳到HttpHandler之前要經過不同的HttpModule的處理。這樣做的好處,一是為了一些必需的過程,二是為了安全性,三是為了提高效率,四是為了用戶能夠在更多的環節上進行控制,增強用戶的控制能力。ASP.NET 3.5運行原理如圖1.1所示。

圖1.1  ASP.NET 3.5運行原理

  說明:HttpModule模塊是一個組件,可以注冊為ASP.NET 3.5請求生命周期的一部分,當處理該組件時,該組件可以讀取或更改請求或響應。HttpModule模塊通常用於執行需要監視每個請求的特殊任務,如安全或站點統計信息。

 (PS:

  HttpModule 概述:

  暫時先不考慮我們自己實現Http Module的情況。在.Net中,Http Module 是實現了IHttpModule接口的程序集。IHttpModule 接口本身並沒有什么好大寫特寫的,由它的名字可以出,它不過是一個普普通通的接口而已。實際上,我們關心的是實現了這些接口的類,如果我們也編寫代碼實現了這個接口,那么有什么用途。一般來說,我們可以將Asp.Net中的事件分成三個級別,最頂層是 應用程序級事件、其次是頁面級事件、最下面是控件級事件,事件的觸發分別與 應用程序周期、頁面周期、控件周期緊密相關。而 Http Module 的作用是與應用程序事件 密切相關的。

  我們通過Http Module在Http請求管道(Pipeline)中注冊期望對應用程序事件做出反應的方法,在相應的事件觸發的時候(比如說BeginRequest事件,它在應用程序收到一個Http請求並即將對其進行處理時觸發),便會調用Http Module注冊了的方法,實際的工作在這些方法中執行。.Net 本身已經有很多的Http Module,其中包括 表單驗證Module(FormsAuthenticationModule), Session 狀態Module(SessionStateModule),輸出緩存Module (OutputCacheModule)等。

更多了解:http://www.cnblogs.com/jimmyzhang/archive/2007/11/25/971878.html

  )

  ASP.NET 3.5運行機制如圖1.2所示。

  通常情況下,ASP.NET框架搭建在Windows Server(服務器版操作系統)+IIS(Web服務器,是Internet信息服務管理器的英文縮寫)環境中,在安裝.NET Framework時,安裝程序將會在IIS中注冊ASP.NET所需的ISAPI擴展(aspnet_isapi.dll),這就使得作為ASP.NET宿主的IIS在接收到客戶端的HTTP請求后,將響應請求的控制權交給ASP.NET運行。

  ASP.NET運行時接收到請求后,會判斷站點是否為第一次被訪問,如果是第一次訪問,則運行初始化工作(如加載Bin目錄中的DLL動態鏈接庫,讀取Web.Config網站配置文件,初始化HttpApplication實例,編譯和加載Global.asax文件等)。ASP.NET運行時還負責創建請求響應線程的HttpContext上下文實例和創建承載響應結果的HttpTextWriter實例。然后,ASP.NET運行時尋找合適的HttpHandler(通常就是具有的ASP.NET頁面)處理HTTP請求,並等HttpHandler返回請求處理結果。最后,ASP.NET運行時在完成一些后續工作之后,如保存Session、異常處理,再通過IIS把響應結構返回給客戶端。

圖1.2  ASP.NET 3.5運行機制

  注意:ASP.NET ISAPI工作的主要任務就是安排ASPNET_WP.exe處理請求,並監視ASPNET_ WP.exe進程的執行情況,如果ASPNET_WP.exe進程不能完成任務,ASP.NET ISAPI就安排一個新的ASPNET_WP.exe來處理工作。ASPNET_WP.exe的主要任務是將請求交給一系列稱為HTTP管道的托管對象。如果把ASP.NET ISAPI比做銷售商,那么ASPNET_WP.exe就是生產商,而HTTP管道就是生產的流水線,負責流水線的小組就是HttpRuntime。生產商ASPNET_WP.exe會將訂單(HTTP請求)交給HttpRuntime小組的工作人員ProcessRequest(HttpWorkerRequest wr),HttpRuntime根據內部的分工,最終由ProcessRequestInternal(HttpWorkerRequest wr)在流水線上進行生產。

 

 

 

 

 

向模塊注冊中添加 precondition 屬性,並將其值設置為managedHandler。

此條件會導致僅在請求 ASP.NET 應用程序資源(例如 .aspx 文件或托管處理程序)時才調用該模塊。該資源中不包括靜態文件(例如 .htm 文件)。

其 configuration 節將類似於以下示例。

復制代碼
<configuration>
  <system.webServer>
    <modules>
      <add name="CustomModule" type="Samples.CustomModule" 
           precondition="managedHandler" />
    </modules>
    <defaultDocument>
      <files>
        <add value="Products.aspx" />
      </files>
    </defaultDocument>
  </system.webServer>
</configuration>
復制代碼
Integrated mode — 集成模式
IIS 7.0 中的一種配置,其中,IIS 和 ASP .NET 基於支持使用 .NET Framework 和本機組件創建的組件的管線共享請求處理。在集成模式中,ASP .NET 組件(如 HTTP 模塊)可用於管理所有 Web 請求,其中包括那些對非 ASP .NET 資源的請求。
復制代碼
 <system.webServer>
    <!--集成模式-->
    <modules>
      <add name="BaseHttpHandler" type="Frame.Core.BaseHttpHandler" />
    </modules>
    <handlers>
 </system.webServer>
復制代碼

 

 zhongkeMVC原理:自定義handler(必須實現IhttpModel,想用請求管道的19個事件就必須實現,init是最主要得方法)並且在web.config注冊

通過web.config配置注冊模塊托管代碼,截獲每次請求到baseHandler,在此分析請求地址中的controller、action,然后反射調用相應的方法,通過VTempalte模板替換所有HTML中相應的值,最后返回給用戶。

ps:baseHandler 在global之前

程序啟動先根據web.config去創建baseHandler並且執行他的init方法,還有VT模板的一些初始化 方法,此時執行了三個方法

this.OnInit(EventArgs.Empty);
this.OnLoad(EventArgs.Empty);
this.OnRender(EventArgs.Empty);

然后才執行 global中的 Application_Start事件(Application_Start 和baseHandler中init只是程序啟動時執行一次,每次請求的時候不再執行那兩個方法)

 

每次回話開始的的時候先執行global中Session_Start然后執行正常的每次請求

每次請求 先執行Application_BeginRequest  然后是baseHandler中的那通過 IHttpHandler.ProcessRequest 調用那三個初始化方法

 

 public class BaseHttpHandler : TemplatePageBase, IHttpModule, IRequiresSessionState
TemplatePageBase 是他的父類  所以先之心BaseHttpHandler 中的方法

2016-7-25
現在的理解 他這個框架沒用注冊任何時間 就是利用 第八個創建請求對象的的時候 就創建了httphandler 然后到11 12事件之間的時候執行里面的processrequest方法,根據分析地址去找控制器 去找html文件, 替換模板內容

 

 一般情況下  稱HttpModel為過濾器  

global中有些方法是和管道中的時間對應的  不過是先執行自定義模塊中管道中綁定的方法,然后在執行global中的 一一對應

 

 

 processRequest調用管道19個事件  到第12個的時候  有一個hanler的processrequest的方法

一般處理程序和aspx頁到12個都執行這個方法

一般處理程序:是程序員寫的處理代碼

aspx:是頁面的整個生命周期

 

 

 

 

托管和非托管是什么意思?

托管代碼 (managed code) :由公共語言運行庫環境(而不是直接由操作系統)執行的代碼。托管代碼應用程序可以獲得公共語言運行庫服務,例如自動垃圾回收、運行庫類型檢查和安全支持等。這些服務幫助提供獨立於平台和語言的、統一的托管代碼應用程序行為。 Unmanaged Code - 非托管代碼 :在公共語言運行庫環境的外部,由操作系統直接執行的代碼。非托管代碼必須提供自己的垃圾回收、類型檢查、安全支持等服務;它與托管代碼不同,后者從公共語言運行庫中獲得這些服務。非托管代碼的英文名是Unmanaged Code ,它是在公共語言運行庫環境的外部,由操作系統直接執行的代碼。

 

 

 

MVC怎么進入管道的

httpapplaction 創建之后會遍歷創建所有module 包括 URLRoutingMdeule路由處理

遍歷完URLRoutingMdeule 執行他的init方法,完成了請求管道中第七個事件的注冊
通過反編譯可以看到 URLRoutingMdeule 注冊了第七個事件
遍歷完 執行 processRequest 開始進入管道 到第七個事件的時候
執行注冊的方法,根據路由數據創建MVChandler 實現了Ihttphanlder
到十一、十二個事件之間 執行 processrequest(去找控制器 、方法)

這個processrequest
asp.net:page_load一系列方法
MVC:去匹配控制器、方法
一般處理程序:程序員直接實現代碼

 

一系列處理 到httpruntime 然后創建 httpcontext 並且對象池獲取 Application

然后進入管道piplines

7/8事件之間  獲取 httpHandler  

 

MVC 生命周期

 

 https://www.cnblogs.com/fzrain/p/3651693.html

 

HttpApplication的處理管道19個事件。

https://www.cnblogs.com/wolf-sun/p/5236185.html

HttpApplication對象是由Asp.net幫助我們創建的,它是asp.net中處理請求的重要對象。為了便於擴展,HttpApplication采用處理管道的方式進行處理,將處理的步驟分為多個步驟,每個步驟通過事件的形式暴露給程序員,這些事件按照固定的處理順序依次觸發,程序員通過編寫事件處理方法就可以定義一個請求的擴展過程。

對於HttpApplication,到ASP.NET 4.0,提供了19個標准事件。

1.BeginRequest:asp.net開始處理請求的第一個事件,表示處理的開始。

2.AuthenticateRequest:驗證請求,一般用來取得請求的用戶信息。

3.PostAuthenticateRequest:已經獲取請求的用戶信息。

4.AuthorizeRequest:授權,一般用來檢查用戶的請求是否獲得權限。

5.PostAuthorizeRequest:用戶請求已經獲得授權。

6.ResolveRequestCache:獲取以前處理緩存的處理結果,如果以前緩存過,那么,不用再進行請求的處理工作,直接返回緩存的結果。

7.PostResolveRequestCache:已經完成緩存的處理工作。

8.PostMapRequestHandler:已經根據用戶的請求,創建了請求的處理器對象。

9.AcquireRequestState:取得請求的狀態,一般用於session

10.PostAcquireRequestState:已經獲得了session

11.PreRequestHandlerExecute:准備執行處理程序。

12.PostRequestHandlerExecute:已經執行了處理程序

13.ReleaseRequestState:釋放請求的狀態。

14.PostReleaseRequestState:已經釋放了請求的狀態。

15.UpdateRequestCache:更新緩存。

16.PostUpdateRequestCache:已經更新了緩存。

17.LogRequest:請求的日志操作

18.PostLogRequest:已經完成請求的日志操作。

19.EndRequest:本次請求處理完成。

ASP.NET MVC中的Global.asax文件

1.global.asax文件概述 

global.asax這個文件包含全局應用程序事件的事件處理程序。它響應應用程序級別和會話級別事件的代碼。  
運行時, Global.asax 將被編譯成一個動態生成的 .NET Framework 類,該類是從HttpApplication基類派生的。
因此在global.asax中的代碼可以訪問HttpApplication類中所有的public或者protected的成員
global.asax不被用戶直接請求,但global.asax中的代碼會被自動執行來響應特定的應用程序事件。
global.asax是可選的,而且在一個web項目中是唯一的,它應該處於網站的根目錄。

2.一個請求的完整處理過程

以下過程由Internet Information Service(inetinfo.exe)(IIS)執行
1.客戶端發出請求
2.驗證請求
3.給請求授權
4.確定請求的緩存
5.獲取緩存狀態
6.在請求的處理程序執行前
7.http處理程序執行請求 (asp.net頁面由aspnet_wp.exe執行)
8.在請求的處理程序執行后
9.釋放請求狀態
10.更新請求緩存
11.請求結束

3.global.asax中的事件

global.asax中的所有事件可以分成兩種,一種是滿足特定事件時才會被觸發,一種是每次請求都會被按照順序執行的事件。

復制代碼
 public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start(object sender, EventArgs e)
        {
            //不是每次請求都調用
            //在Web應用程序的生命周期里就執行一次
            //在應用程序第一次啟動和應用程序域創建事被調用
            //適合處理應用程序范圍的初始化代碼
        }

        void Application_End(object sender, EventArgs e)
        {
            //不是每次請求都調用
            //在應用程序關閉時運行的代碼,在最后一個HttpApplication銷毀之后執行
            //比如IIS重啟,文件更新,進程回收導致應用程序轉換到另一個應用程序域
        }

        void Session_Start(object sender, EventArgs e)
        {
            //不是每次請求都調用
            //會話開始時執行
        }

        void Session_End(object sender, EventArgs e)
        {
            //不是每次請求都調用
            //會話結束或過期時執行
            //不管在代碼中顯式的清空Session或者Session超時自動過期,此方法都將被調用
        }

        void Application_Init(object sender, EventArgs e)
        {
            //不是每次請求都調用
            //在每一個HttpApplication實例初始化的時候執行
        }

        void Application_Disposed(object sender, EventArgs e)
        {
            //不是每次請求都調用
            //在應用程序被關閉一段時間之后,在.net垃圾回收器准備回收它占用的內存的時候被調用。
            //在每一個HttpApplication實例被銷毀之前執行
        }

        void Application_Error(object sender, EventArgs e)
        {
            //不是每次請求都調用
            //所有沒有處理的錯誤都會導致這個方法的執行
        }


        /*********************************************************************/
        //每次請求都會按照順序執行以下事件
        /*********************************************************************/

        void Application_BeginRequest(object sender, EventArgs e)
        {
            //每次請求時第一個出發的事件,這個方法第一個執行
        }

        void Application_AuthenticateRequest(object sender, EventArgs e)
        {
            //在執行驗證前發生,這是創建驗證邏輯的起點
        }

        void Application_AuthorizeRequest(object sender, EventArgs e)
        {
            //當安全模塊已經驗證了當前用戶的授權時執行
        }

        void Application_ResolveRequestCache(object sender, EventArgs e)
        {
            //當ASP.NET完成授權事件以使緩存模塊從緩存中為請求提供服務時發生,從而跳過處理程序(頁面或者是WebService)的執行。
            //這樣做可以改善網站的性能,這個事件還可以用來判斷正文是不是從Cache中得到的。
        }

        //------------------------------------------------------------------------
        //在這個時候,請求將被轉交給合適程序。例如:web窗體將被編譯並完成實例化
        //------------------------------------------------------------------------

        void Application_AcquireRequestState(object sender, EventArgs e)
        {
            //讀取了Session所需的特定信息並且在把這些信息填充到Session之前執行
        }

        void Application_PreRequestHandlerExecute(object sender, EventArgs e)
        {
            //在合適的處理程序執行請求前調用
            //這個時候,Session就可以用了
        }

        //-------------------------------------------------
        //在這個時候,頁面代碼將會被執行,頁面呈現為HTML
        //-------------------------------------------------

        void Application_PostRequestHandlerExecute(object sender, EventArgs e)
        {
            //當處理程序完成對請求的處理后被調用。
        }

        void Application_ReleaseRequestState(object sender, EventArgs e)
        {
            //釋放請求狀態
        }

        void Application_UpdateRequestCache(object sender, EventArgs e)
        {
            //為了后續的請求,更新響應緩存時被調用
        }

        void Application_EndRequest(object sender, EventArgs e)
        {
            //EndRequest是在響應Request時最后一個觸發的事件
            //但在對象被釋放或者從新建立以前,適合在這個時候清理代碼
        }

        void Application_PreSendRequestHeaders(object sender, EventArgs e)
        {
            //向客戶端發送Http標頭之前被調用
        }

        void Application_PreSendRequestContent(object sender, EventArgs e)
        {
            //向客戶端發送Http正文之前被調用
        }
    }
復制代碼

 

 

原文: https://technet.microsoft.com/zh-cn/sysinternals/bb763179.aspx

          https://www.cnblogs.com/lgxlsm/p/5573088.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM