程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> .NET實例教程 >> Asp.net Ajax 1.0 異步回調時,服務器端Render原理

Asp.net Ajax 1.0 異步回調時,服務器端Render原理

編輯:.NET實例教程


首冼回顧一下
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();            
    }      &n
bsp;     
    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啦,怎麼辦      &nbs
p;     
    //手動處理一個呗              
    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)             
    {                
        fo
reach (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
http://www.cnblogs.com/liuxu-wxy/archive/2007/04/25/727346.Html

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved