我對Asp.net頁面一系列執行過程的認識

iDotNetSpace發表於2010-08-20
眾所周知,每個asp.net頁面都是一個HttpHandler,並且它也是一個控制元件。我們來看來它的本身定義。

 

<!--Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--&gtpublic class Page : TemplateControl,IHttpHandler 
{


  當IIS處理http的請求時,都會根據請求的副檔名來判斷,找到對應的ISAPI,ISAPI主要負責與

ASP.NET程式之間進行通訊。Asp.net程式會進行一系統初始化工作,比如建立一個HttpRunTime執行

 環境,等等一系統的操作,這個原理園子裡很多朋友都寫了,最終的請求都會找到一個Handler來執行,

我們平時寫的asp.net頁面就是一個handler,所以它可以處理請求,而這個Handler的入口點就是從

ProcessRequest()方法開始的。

  上面說了這麼廢話,無非就是想說 ProcessRequest()這個方法到底幹了些什麼”勾當“,我從IL的

角度來重新認識它。

  我先列出來Page類中一些非常重要的方法:

 

<!--Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--&gtpublic class Page : TemplateControl,IHttpHandler 
{
    
//用於處理回發資料的方法
    private void ProcessPostData(NameValueCollection postData, bool fBeforeLoad);
    
// 頁面處理請求入口點
    private void ProcessRequest();
    
//呼叫了帶引數的ProcessRequestMain()
    private void ProcessRequestMain();
    
//頁面核心處理方法,執行一系列的我們平時熟悉的方法,事件(如Page_Init,Page_Load....)
    private void ProcessRequestMain(bool includeStagesBeforeAsyncPoint, bool includeStagesAfterAsyncPoint);


   我們先從入口處方法進入,先看看ProcessRequest();方法到底幹了些什麼,簡單地註釋了一下。

<!--Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--&gtprivate void ProcessRequest()
{
    
//設定語言文化資訊
    Thread currentThread = Thread.CurrentThread;
    CultureInfo currentCulture 
= currentThread.CurrentCulture;
    CultureInfo currentUICulture 
= currentThread.CurrentUICulture;
    
try
    { 
       
//這其中又過載了一次
        this.ProcessRequest(truetrue);
    }
    
finally
    {
        
this.RestoreCultures(currentThread, currentCulture, currentUICulture);
    }
}

//我簡化了程式碼
private void ProcessRequest(bool includeStagesBeforeAsyncPoint, bool includeStagesAfterAsyncPoint)
{
    
if (includeStagesBeforeAsyncPoint)
    {
        
this.FrameworkInitialize();   //框架初始化
    }
    
try
    { 
       
//這個才是重點,所有處理全在這個方法裡
       this.ProcessRequestMain(includeStagesBeforeAsyncPoint, includeStagesAfterAsyncPoint);
    }
    
catch
    {
        
throw;
    }
}

  終於講到重點了。我們先看看ProcessRequestMain方法的IL,註釋全寫程式碼裡了,基本都是我們平時熟悉的事件。


<!--Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--&gt//簡化了許多,去掉了一些與除錯與跟蹤的程式碼
        private void ProcessRequestMain(bool includeStagesBeforeAsyncPoint, bool includeStagesAfterAsyncPoint)
        {
            
try
            {
                HttpContext context 
= this.Context;
                
string str = null;
                
if (includeStagesBeforeAsyncPoint)
                {
                    
//預初始化,設定母版頁與應用主題等操作
                    this.PerformPreInit();

                    
//遞迴初始化,如果該控制元件包括子控制元件,則依次從內至外開始初始化(子控制元件->父控制元件)
                    this.InitRecursive(null);

                    
//初始化完畢
                    this.OnInitComplete(EventArgs.Empty);

                    
//如果為回發
                    if (this.IsPostBack)
                    {
                        
//對那些啟用了檢視狀態的控制元件依次載入檢視資料,在這個階段,我們非常熟悉的Page.LoadPageStateFromPersistenceMedium()
                        
//方法將會執行
                        this.LoadAllState();

                        
//處理回發資料,該方法在load前與load之後都要執行,ProcessPostData這個方法說起來可以有一大堆,我準備另起一篇再講這個
                        
//東東,在Page_Load之前執行時(即fBeforeLoad為true)時,它裡面主要就是對那些實現了IPostBackDataHandler介面的控制元件
                        
//處理Post資料,註冊Post資料處理事件,其實也就是很常見的LoadPostData();
                        
//RegisterRequiresRaiseEvent(control.PostBackEventHandler);儲存那些未得到初始化的控制元件目的為了下一次的ProcessData..
                        
//.....等操作
                        this.ProcessPostData(this._requestValueCollection, true);
                    }
                    
//終於快到頁面載入了
                    this.OnPreLoad(EventArgs.Empty);

                    
//迴圈執行Load事件,方法迴圈執行控制元件的Load事件,如果控制元件包括子控制元件,則從外到內執行(父控制元件->子控制元件),
                    
//執行順序正常與InitRecursive()方法相反,Page_Load事件在此執行
                    this.LoadRecursive();


                    
if (this.IsPostBack)
                    {
                        
//第二次處理回發資料,本次處理的控制元件上次沒得到處理的剩下的控制元件
                        this.ProcessPostData(this._leftoverPostData, false);

                        
//這個方法主要是引發那些需要處理回發資料的控制元件在資料改變時需要引發的事件,如textbox控制元件的textchanged事件
                        
//比如:postBackDataHandler.RaisePostDataChangedEvent();

                        
this.RaiseChangedEvents();

                        
//引起控制元件的回發事件,平時我們常用的控制元件的,如Button的click事件在這一步執行
                        this.RaisePostBackEvent(this._requestValueCollection);
                    }

                    
//頁面載入完畢
                    this.OnLoadComplete(EventArgs.Empty);
                }

                
//驗證
                this._request.ValidateRawUrl();

                
//預呈現
                this.PerformPreRenderComplete();

                
//儲存檢視狀態 ,如: this.SavePageStateToPersistenceMedium(state);   
                this.SaveAllState();

                
this.OnSaveStateComplete(EventArgs.Empty);
                
//最後一步當就就是呈現了。
                this.RenderControl(this.CreateHtmlTextWriter(this.Response.Output));
            }
            
catch (ThreadAbortException exception)
            {

            }
            
catch (ConfigurationException)
            {

            }
            
catch (Exception exception3)
            {

            }
        }

   這就是整個Page的從請求到輸出整個一系統的執行過程,能過上面的程式碼能看得出來,Page頁面大部分的處理邏輯都在 ProcessRequestMain()方法中,這就是我通過IL再一次看清楚Page的執行過程。希望能更清晰展示出來和大家 一起分享!

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-671450/,如需轉載,請註明出處,否則將追究法律責任。

相關文章