Asp.net Ajax 1.0 非同步回調時,伺服器端Render原理

來源:互聯網
上載者:User
Asp.net Ajax 1.0 非同步回調時,伺服器端Render原理首冼回顧一下
Page頁的生命週期

PreInit
Init
InitComplete
LoadState
ProcessPostData
PreLoad
Load
LoadComplete
PreRender      
PrepareCallback //如果有回調
PreRenderComplete
SaveState
SaveStateComplete
Render

不論是Asp.net請求,還是Ajax請求,都要執行上面的頁生命週期,

在Page頁最後會調用Page.RenderControl()呈現Page所有子控制項

流程如下

Page.RenderControl
      Control.RenderControl()
             Control.RenderControl(writer,this.Adapter)
                   Control.RenderControlInternal()
                       Control.Render()   //此時Page.Render()將其重寫
                            Control.RenderChildren()
                                  Control.RenderControlInternal()

現在關鍵所在
Control.RenderControlInternal()實現如下
如果不是Asp.net Ajax處理,肯定會執行foreach依次對所有的子控制項進行遍曆

 internal void RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
 {           
    //正常情況如果不設定RareFields,進行預設的流程依次對所有子控制項進行處理,           
    //如果設定RareFields,意思就是以自訂的方式改寫RenderChildren           
    if ((this.RareFields != null) && (this.RareFields.RenderMethod != null))     //當您SetRenderMethodDelegate時,RareFieldsEnsured就有值啦           
    {               
        writer.BeginRender();          
    
        //調用RenderMethod委託,Asp.net Ajax1.0在使用Control.SetRenderMethodDelegate時,對應的回呼函數就是在此時處理的               
        this.RareFields.RenderMethod(writer, this);               
        writer.EndRender();           
    }           
    else if (children != null)           
    {                
        //如果不設定這個RareFieldsEnsured,會把Page裡所有的控制項呈現               
        //依次調用Control裡所有子控制項的RenderControl               
        foreach (Control control in children)               
        {                   
           control.RenderControl(writer);               
        }            
    }
       
}

以上是Asp.net 的Render處理
肯定有人要問上面的if是幹嗎的,這個可是微軟流的介面呀,整個asp.net ajax全靠這個介面進行處理

在Asp.netAjax1.0上,你肯定要放一個ScriptManager吧
它也是Control的子類,
在Page生命週期的OnPreRender時,它會調用

PageRequestManager.OnPreRender();       

問題就在這,PageRequestManager.OnPreRender()實現如下

_owner.IPage.SetRenderMethodDelegate(RenderPageCallback);

SetRenderMethodDelegate()方法是幹什麼用的

在Control中,當您調用了SetRenderMethodDelegate會給Control.RareFieldsEnsured設定值
   public void SetRenderMethodDelegate(RenderMethod renderMethod)
        {
            //使用OccasionalFields.RareField
            this.RareFieldsEnsured.RenderMethod = renderMethod;
            this.Controls.SetCollectionReadOnly("Collection_readonly_Codeblocks");
        }

到這一切就清晰了,當您設定了RenderPageCallback,正常的Asp.net流程就不會再走了,所有的子控制項就不會被Render
在Asp.netAjax 1.0中使用

private void RenderPageCallback(HtmlTextWriter writer, Control pageControl)
{          
     ...
    //取出當前的HtmlForm
    IHtmlForm formControl = _owner.IPage.Form;  
            
    //手動設定當FormControl.RenderControl時()回調方法  ,因為這個時候Page.Controls裡有子控制項不會被Render啦,怎麼辦           
    //手動處理一個唄             
    formControl.SetRenderMethodDelegate(RenderFormCallback);
           
    //同樣,HtmlForm.RenderControl不會在Page.Controls裡自動觸發的
    //這個時候您需要手動的RenderCtronl一下,這樣才能調用RenderFormCallback           
    formControl.RenderControl(formWriter); 
           
    //產生用戶端回調資訊|asyncPostBackControlIDs
    EncodeString(writer, AsyncPostBackControlIDsToken, String.Empty, GetAsyncPostBackControlIDs(false));           
    //產生用戶端回調資訊 |postBackControlIDs
    EncodeString(writer, PostBackControlIDsToken, String.Empty, GetPostBackControlIDs(false));           
    //產生用戶端回調資訊 |updatePanelIDs|tUpdatePanel         
    EncodeString(writer, UpdatePanelIDsToken, String.Empty, GetAllUpdatePanelIDs());    
    //產生用戶端回調資訊 |childUpdatePanelIDs     
    EncodeString(writer, ChildUpdatePanelIDsToken, String.Empty, GetChildUpdatePanelIDs());           
    //產生用戶端回調資訊 |panelsToRefreshIDs
    EncodeString(writer, UpdatePanelsToRefreshToken, String.Empty, GetRefreshingUpdatePanelIDs());           
    //產生用戶端回調資訊 |asyncPostBackTimeout           
    EncodeString(writer, AsyncPostBackTimeoutToken, String.Empty, _owner.AsyncPostBackTimeout.ToString(CultureInfo.InvariantCulture));
          
........
       
}
       
private void RenderFormCallback(HtmlTextWriter writer, Control containerControl)        
{         
   ....          
    //呈現所有的UpdatePanel           
    if (_updatePanelsToRefresh != null)            
    {               
        foreach (UpdatePanel panel in _updatePanelsToRefresh)                
        {                  
            if (panel.Visible)                   
            {                
                panel.RenderControl(_updatePanelWriter);        
                //    會產生如何的用戶端回調資訊    
                //169|updatePanel|UpdatePanel1|/r/n              
            }               
         }
           
    }     
     ...                  
    //依次將頁面上所有控制項的RenderControl,寫入dummyWriter                   
    foreach (Control control in containerControl.Controls)                    
    {                       
         control.RenderControl(dummyWriter);  
         //產生一部分資訊
         <input type=/"submit/" name=/"Button1/" value=/"Button/" id=/"Button1/" />/r/n              
         <input name=/"txt/" type=/"text/" value=/"wxy/" id=/"txt/" />/r/n                 
    }       

    注意,在RenderFormCallback時,HttpRequest會手動的Flush()將上面的資訊刷加IIS
}

至於Ctronl.Render時,是如何寫入HtmlTextWriter,再寫入HttpWriter,
再寫回HttpWorkRequest,最終刷回核心,或使用socket發送回伺服器,不在本文討論範圍.......

由上可見,Asp.net Ajax,必沒有使用傳統的HttpRequest.Filter來處理回傳資訊,而是使用了Asp.net 2.0內建的方式和回調的

Asp.net Ajax回調後呈現到用戶端有二個部分,一部分是由RenderFormCallback產生的如下

  RenderFormCallback部分會產生如下的用戶端指令碼        
 169|updatePanel|UpdatePanel1|/r/n  
 
<input type=/"submit/" name=/"Button1/" value=/"Button/" id=/"Button1/" />/r/n              
 <input name=/"txt/" type=/"text/" value=/"wxy/" id=/"txt/" />/r/n  

一部分是RenderPageCallback產生的

 52|hiddenField
|__VIEWSTATE|/wEPDwUJNjg1NjA3NDcxZGRCX32AH2I/NEq+gCFrVr49kQDECw==|56
|hiddenField|__EVENTVALIDATION|/wEWAwKf344xAoznisYGApKGsMIJOfjKisKPYP0O2NXUpNjnA29hMlA=|0
|asyncPostBackControlIDs|||0|postBackControlIDs|||13|updatePanelIDs||tUpdatePanel1|0
|childUpdatePanelIDs|||12|panelsToRefreshIDs||UpdatePanel1|2|asyncPostBackTimeout||90|12
|formAction||Default.aspx|13|pageTitle||Untitled Page|

在用戶端的部分Sys.WebForm._onFormSubmitCompleted()會對所有的資訊以Json type:type,id:id,content:content進行封裝
取出UpdatePanel,設定其innerhtml,用戶端詳細部分見趙老大的blogs

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.