無刷新頁面的做法(Framework 1.1 /2.0)轉自RBMXXX的Blog

  n         ASP.NET1.1中的Postback機制

n         ASP.NET2.0中的新功能Script Callback介紹

n         如何使用Script Callback IN ASP.NET 2.0

n         如何使用Script Callback IN ASP.NET 1.1

n         思考與問題

n         作者信息

ASP.NET1.1中的Postback機制

asp.net1.1中,我們知道每個服務器控件都有一個AutoPostback屬性。它的作用是當用戶(客戶端)修改該控件的值,即也可以說是當該控件的事件觸發的時候,客戶端就通過JavaScript__doPostback(object,EventArgument)來和服務端實現通信。它使得程序員在實現動態的獲取服務端數據變得非常方便。例如:有一個查詢成績的頁面,由一個DrowDownlist和一個DataGrid來實現。其中DropDownlist從服務綁定所要查看的學期(2003-2004上半學期,2003-2004下半學期等),DataGrid而是用來顯示他在改學期所有科目的成績,和該學科的學分。在ASP.NET1.1中我們最常使用的方法也就是將DrowDownlistAutoPostback屬性設置爲True,並把該事件觸發服務端後臺的某個方法,該方法獲取所選擇的學期的id號,然後去數據庫獲得DataTable重新綁定與DataGrid並將它顯示出來。在這整個過程中,作爲用戶肯定是要經歷一個刷新頁面的過程。如果僅像剛纔那個例子所說這個刷新不會很大的影響用戶的Experience,不過如果你有一個複雜的填寫表單的頁面,該頁面有大量的Control是相關的,需要更據其它Control的選擇情況去動態的綁定數據,那當用戶填完這個表單的時候也許眼睛也花了,他也許再也不想經歷如此痛苦的折磨了,從Experience方面來講將是非常差的。在不是從服務端獲取大量數據的情況下,我們要如何才能避免這種在用戶看似多餘的Postback?

ASP.NET2.0中新功能Script Callback介紹

ASP.NET2.0中,客戶端的腳本功能已經被擴展了。並且增加了Script Callbacks(通過腳本建立於後臺的鏈接,後文將其翻譯爲客戶端呼叫)。你可以用程序去控制<head>標籤,通過程序控制input焦點,讀取或者設置頁面的標題,並且可以控制button或其他的控件提交到其他任何頁面(in the application)。具體您可以查看Beta 1 說明,裏面有例子和參考。

爲了使用ASP.NET2.0中的客戶端呼叫技術,你需要在頁面中定義一個觸發元件(不是提交按鈕Submit button)並且把它綁定上JavaScript代碼。這段代碼會重新獲得當前頁面的input數據並且準備去呼叫系統提供的一個稱爲WebForm_DoCallbackScript函數(Beta1)。這個函數會建立一個和一個指定的遠程ASP.NET頁面建立HTTP連接。後臺偵聽到這個來自客戶端的呼叫後呢,對此觸發一個方法。服務端通過先前的客戶端的函數返回一個值。在客戶端,通過一個用戶自定義的腳本函數來獲得服務端的值並且用DHTML將其呈現在頁面上。重要的是,這樣做客戶端和服務端的通信仍舊在進行,但是頁面並沒有重新刷新。更重要的是,當客戶端在獲取數據的時候用戶仍舊可以在它原來的頁面上操作。圖片1,顯示了客戶端呼叫的流程。

 Figer1

 

                     圖片1

如何使用Script Callback IN ASP.NET 2.0

ASP.NET2.0中使用Script Callback 主要有兩個步驟。首先,需要寫服務端的代碼,這段代碼將會被客戶端所調用。當然,必須前定義數據你將要返回的數據類型。這就要更具你需要聲麼數據而定了。實際上他們通信的都是用String的,但是這個字符串的內容就可以是多種多樣的——JavaScript,XML,’,’分隔的string值,等等。

然後,你需要寫客戶端的代碼去引起一個無刷新的呼叫。遠程的響應是建立在一個叫WebForm_DoCallbackJavaScript函數。你其實沒有必要去知道這個函數的名字,你可以從Page類的新成員——GetCallbackEventReference()中獲得客戶端呼叫。

 Finger2

 

 

string callbackRef = Page.ClientScript.GetCallbackEventReference(this, "document.all['DropDownList1'].value", "UpdateInfo", "null");

注意:在我當前的版本中,也是最新的版本中GetCallbackEventReference不是Page的一個屬性而是Page.ClientScript屬性的一個方法,該方法有三個重載詳見msdn

而呼叫這個javaScript函數的是綁定在一個可以點擊的元素上,例如<button>標記。所以這個可以點擊的元素,不能是<asp:button>控件,因爲這樣的服務端控件客戶端呈現爲一個提交按鈕:

<input type=”submit” id=”button” …>

置於ASP.NET2.0中是如何實現Callback全過程在此省略,詳情請看作者原文。

需要說明的是:爲了能在服務端檢測到頁面元素使用了Script Callback 必須在頁面中引用以下接口,在ASP.NET1.1中也如此。

<%@ Impements Interface=”System.Web.UI.ICallbackEventHandler” %>

如果控件實現了這個接口,ASP.NET後臺就調用RaiseCallbackEvent 方法,並且針對呼叫返回響應。

如下是ICallbackEventHandler 接口中的一個方法:

string RaiseCallbackEvent(string eventArgumen)

當然這個string 是可以表示爲任何你所需要的值,如前面所說的XML,JAVASCRIPT,數值,等等。

以下是我仿照作者的Demo更具最新的Freamwork的一個例子:

scriptCallback.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="ScriptCallback.aspx.cs" Inherits="ScriptCallback_aspx" %> 

<%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %> 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> 

<html xmlns="http://www.w3.org/1999/xhtml"> 

<head runat="server"> 

    
<title>ScriptCallback</title> 

    
<script language=javascript> 

        
function UpdateInfo(result,context) 

        { 

            var o 
= result.split(","); 

            

            
e_ID.innerHTML = o[0]; 

            
e_UserName.innerHTML = o[1]; 

            
e_Password.innerHTML = o[2]; 

            
e_Authority.innerHTML = o[3]; 

            
e_BlogName.innerHTML = o[4]; 

            
e_Email.innerHTML = o[5]; 

        


    </script
> 

</head> 

<body> 

    
<form id="form1" runat="server"> 

        
<div> 

            
<h1> 

                
<span style="font-family: Verdana">Select a name and click for details</span></h1> 

         

                

                    
<asp:DropDownList DataSourceID="SqlDataSource1" DataTextField="UserName" DataValueField="UserName" 

                        ID
="DropDownList1" runat="server"> 

                    
</asp:DropDownList> 

                    
<button runat=server id=btn>More Info</button> 

                    
<asp:SqlDataSource ConnectionString="<%$ ConnectionStrings:COMMConnectionString %>" 

                        ID
="SqlDataSource1" runat="server" SelectCommand="SELECT [UserName] FROM [UserConfig]"> 

                    
</asp:SqlDataSource> 

                    
&nbsp; 

                    
<table style="width: 506px"> 

                        
<tr> 

                            
<td style="width: 89px"> 

                                ID
</td> 

                            
<td style="width: 311px"> 

                            
<span id="e_ID" /> 

                            
</td> 

                        
</tr> 

                        
<tr> 

                            
<td style="width: 89px; height: 20px"> 

                                UserName
</td> 

                            
<td style="width: 311px; height: 20px;"> 

                            
<span id="e_UserName" /> 

                            
</td> 

                        
</tr> 

                        
<tr> 

                            
<td style="width: 89px"> 

                                Password
</td> 

                            
<td style="width: 311px"> 

                            
<span id="e_Password" /> 

                            
</td> 

                        
</tr> 

                        
<tr> 

                            
<td style="width: 89px"> 

                                Authority
</td> 

                            
<td style="width: 311px"> 

                            
<span id="e_Authority" /> 

                            
</td> 

                        
</tr> 

                        
<tr> 

                            
<td style="width: 89px"> 

                                BlogName
</td> 

                            
<td style="width: 311px"> 

                            
<span id="e_BlogName" /> 

                            
</td> 

                        
</tr> 

                        
<tr> 

                            
<td style="width: 89px"> 

                                Email
</td> 

                            
<td style="width: 311px"> 

                            
<span id="e_Email" /> 

                            
</td> 

                        
</tr> 

                    
</table> 

              

           

        
</div> 

    
</form> 

</body> 

</html> 


後臺代碼如下:scriptCallback.aspx.cs

顯示時效如下圖:


using System; 

using System.Data; 

using System.Configuration; 

using System.Collections; 

using System.Web; 

using System.Web.Security; 

using System.Web.UI; 

using System.Web.UI.WebControls; 

using System.Web.UI.WebControls.WebParts; 

using System.Web.UI.HtmlControls; 

  

public partial class ScriptCallback_aspx : System.Web.UI.Page 



    
protected void Page_Load(object sender, EventArgs e) 

    
{        

        
string callbackRef = Page.ClientScript.GetCallbackEventReference(this"document.all['DropDownList1'].value""UpdateInfo""null"); 

           
//給buttom按鈕添加事件,該事件由GetCallbackEventReference產生。 

        btn.Attributes[
"onclick"= String.Format("javascript:{0}",callbackRef); 

  

    }
 

    
public virtual string RaiseCallbackEvent(string eventArgument) 

    


        
//int userID = Convert.ToInt16(eventArgument); 

        
//此處本該是更具eventArgument去數據庫獲取數據的,作爲演示就省去了數據連接,直接//更具不同的eventArgument顯示既定的數據即可。 

        
string[] buf = new string[6]; 

        

        buf[
0= eventArgument + "'s ID"

        buf[
1= eventArgument; 

        buf[
2= eventArgument + "'s Password"

        buf[
3= eventArgument + "'s Authority"

        buf[
4= eventArgument + "'s BlogName"

        buf[
5= eventArgument + "'s Email"

  

        
return String.Join(",", buf); 

    }
 

}
 

 

using System; 

using System.Data; 

using System.Configuration; 

using System.Collections; 

using System.Web; 

using System.Web.Security; 

using System.Web.UI; 

using System.Web.UI.WebControls; 

using System.Web.UI.WebControls.WebParts; 

using System.Web.UI.HtmlControls; 

  

public partial class ScriptCallback_aspx : System.Web.UI.Page 



    
protected void Page_Load(object sender, EventArgs e) 

    
{        

        
string callbackRef = Page.ClientScript.GetCallbackEventReference(this"document.all['DropDownList1'].value""UpdateInfo""null"); 

           
//給buttom按鈕添加事件,該事件由GetCallbackEventReference產生。 

        btn.Attributes[
"onclick"= String.Format("javascript:{0}",callbackRef); 

  

    }
 

    
public virtual string RaiseCallbackEvent(string eventArgument) 

    


        
//int userID = Convert.ToInt16(eventArgument); 

        
//此處本該是更具eventArgument去數據庫獲取數據的,作爲演示就省去了數據連接,直接//更具不同的eventArgument顯示既定的數據即可。 

        
string[] buf = new string[6]; 

        

        buf[
0= eventArgument + "'s ID"

        buf[
1= eventArgument; 

        buf[
2= eventArgument + "'s Password"

        buf[
3= eventArgument + "'s Authority"

        buf[
4= eventArgument + "'s BlogName"

        buf[
5= eventArgument + "'s Email"

  

        
return String.Join(",", buf); 

    }
 

}
 

 

 

爲了將此新特新運用在ASP.NET1.1中,我們來挖掘一下,在.NET2.0中到底是如何實現的。

以下是跟蹤過程:用birdsome介紹的方法點擊more info前打開在下一步按Alt->v->u->b然後點擊more info

<button id="btn" onclick="javascript:WebForm_DoCallback('__Page',document.all['DropDownList1'].value,UpdateInfo,null,null,false)">More Info</button>

從此處可以知道button已經綁定上了由GetCallbackEventReference產生的腳本。在這個版本中並沒有這個腳本的名字還是叫WebForm_DoCallbackNever Mind!繼續,F11……

<script src="/ExperienceAspx2.0/WebResource.axd?a=s&amp;r=WebForms.js&amp;t=632430413780000000" type="text/javascript"></script>

我們還發現在頁面中系統加上了上面這段腳本。WebResource.axd是一個在ASP.NET中新的內置於HTTP的處理中。用它把腳本程序包含到頁面中。這個handler確保把所有的控件或者頁面的Callback引用腳本包含進來。並且,webResource.axd確保所有的WebForm_DoCallbackWebForm_InitCallback成功的被執行。

下面我們就揭開它的真面目:

 

這個版本的WebResource.axd中包含的函數有:

function WebForm_PostBackOptions(eventTarget, eventArgument, validation, validationGroup, actionUrl, trackFocus, clientSubmit)

function WebForm_DoPostBackWithOptions(options)

function WebForm_DoCallback(eventTarget, eventArgument, eventCallback, context, errorCallback, useAsync)

function WebForm_CallbackComplete()

function WebForm_InitCallback()

function WebForm_ReEnableControls()

function WebForm_ReDisableControls()

function WebForm_FireDefaultButton(event, target)

function WebForm_GetScrollX()

function WebForm_GetScrollY()

function WebForm_SaveScrollPositionSubmit()

function WebForm_SaveScrollPositionOnSubmit()

function WebForm_RestoreScrollPosition()

function WebForm_TextBoxKeyHandler()

我們只研究其中的WebForm_DoCallback,和WebForm_CallbackComplete,其他完整的代碼我將在提供打包下載。

var __callbackObject = new Object();

function WebForm_DoCallback(eventTarget, eventArgument, eventCallback, context, errorCallback, useAsync) {

    re 
= new RegExp("//x2B""g");

    
var postData = __theFormPostData +

                
"__CALLBACKID=" + eventTarget +

                
"&__CALLBACKPARAM=" + escape(eventArgument).replace(re, "%2B");

    
if (__nonMSDOMBrowser) {

        
var xmlRequest = new XMLHttpRequest();

        
if (pageUrl.indexOf("?"!= -1) {

            xmlRequest.open(
"GET", pageUrl + "&" + postData, false);

        }

        
else {

            xmlRequest.open(
"GET", pageUrl + "?" + postData, false);

        }

        xmlRequest.setRequestHeader(
"Content-Type""application/x-www-form-urlencoded");

        xmlRequest.send(
null);

        response 
= xmlRequest.responseText;

        
if (response.charAt(0== "s") {

            
if (eventCallback != null) {

                eventCallback(response.substring(
1), context);

            }

        }

        
else {

            
if (errorCallback != null) {

                errorCallback(response.substring(
1), context);

            }

        }

    }

    
else {

        
var xmlRequest = new ActiveXObject("Microsoft.XMLHTTP");

        xmlRequest.onreadystatechange 
= WebForm_CallbackComplete;

        __callbackObject.xmlRequest 
= xmlRequest;

        __callbackObject.eventCallback 
= eventCallback;

        __callbackObject.context 
= context;

        __callbackObject.errorCallback 
= errorCallback;

        
var usePost = false;

        
if (pageUrl.length + postData.length + 1 > 2067) {

            usePost 
= true;

        }

        
if (usePost) {

            xmlRequest.open(
"POST", pageUrl, useAsync);

            xmlRequest.setRequestHeader(
"Content-Type""application/x-www-form-urlencoded");

            xmlRequest.send(postData);

        }

        
else {

            
if (pageUrl.indexOf("?"!= -1) {

                xmlRequest.open(
"GET", pageUrl + "&" + postData, useAsync);

            }

            
else {

                xmlRequest.open(
"GET", pageUrl + "?" + postData, useAsync);

            }

            xmlRequest.setRequestHeader(
"Content-Type""application/x-www-form-urlencoded");

            xmlRequest.send();

        }

    }

}


可見在該版本中比作者原文的WebForm_DoCallback有了很大的改進。

var __callbackObject = new Object();

function WebForm_DoCallback(eventTarget, eventArgument, eventCallback, context, errorCallback, useAsync) {

    re 
= new RegExp("//x2B""g");

    
var postData = __theFormPostData +

                
"__CALLBACKID=" + eventTarget +

                
"&__CALLBACKPARAM=" + escape(eventArgument).replace(re, "%2B");

    
if (__nonMSDOMBrowser) {

        
var xmlRequest = new XMLHttpRequest();

        
if (pageUrl.indexOf("?"!= -1) {

            xmlRequest.open(
"GET", pageUrl + "&" + postData, false);

        }

        
else {

            xmlRequest.open(
"GET", pageUrl + "?" + postData, false);

        }

        xmlRequest.setRequestHeader(
"Content-Type""application/x-www-form-urlencoded");

        xmlRequest.send(
null);

        response 
= xmlRequest.responseText;

        
if (response.charAt(0== "s") {

            
if (eventCallback != null) {

                eventCallback(response.substring(
1), context);

            }

        }

        
else {

            
if (errorCallback != null) {

                errorCallback(response.substring(
1), context);

            }

        }

    }

    
else {

        
var xmlRequest = new ActiveXObject("Microsoft.XMLHTTP");

        xmlRequest.onreadystatechange 
= WebForm_CallbackComplete;

        __callbackObject.xmlRequest 
= xmlRequest;

        __callbackObject.eventCallback 
= eventCallback;

        __callbackObject.context 
= context;

        __callbackObject.errorCallback 
= errorCallback;

        
var usePost = false;

        
if (pageUrl.length + postData.length + 1 > 2067) {

            usePost 
= true;

        }

        
if (usePost) {

            xmlRequest.open(
"POST", pageUrl, useAsync);

            xmlRequest.setRequestHeader(
"Content-Type""application/x-www-form-urlencoded");

            xmlRequest.send(postData);

        }

        
else {

            
if (pageUrl.indexOf("?"!= -1) {

                xmlRequest.open(
"GET", pageUrl + "&" + postData, useAsync);

            }

            
else {

                xmlRequest.open(
"GET", pageUrl + "?" + postData, useAsync);

            }

            xmlRequest.setRequestHeader(
"Content-Type""application/x-www-form-urlencoded");

            xmlRequest.send();

        }

    }

}


可見在該版本中比作者原文的WebForm_DoCallback有了很大的改進。

在原文中作者給出了兩個不要直接調用WebForm_oCallback的理由,第一是可以通過Client Script Mangner來管理用其GetCallbackEventReference方法來實現客戶端的腳本,第二由於,WebForm_DoCallback不是Page API的所以在以後的版本中不能保證它不改名字,並且,如果其有新的修改也不會有對外公佈的必要。

從該代碼中可以發現它不僅適用於ie,對其他瀏覽器也提供了支持。它使用了一個COM對象從特定的URL中來接受發送數據。

然後在HTTP傳送數據時是選擇POST,還是GET是取決於數據的大小。如果大於2K的數據則採用POSTHTTP請求包含3個基本元素:__CALLBACKID,__CALLBACKPARAM,和發送的數據包。__CALLBACKID中包含目標地址,而__CALLBACKPARAM則是攜帶者服務段方法需要的參數。發送的數據包氏通過WebFrom_InitCallback方法來連接並且附加HTTP命令中。以上代碼詳細呈現了該實現過程。

如何使用Script Callback IN ASP.NET 1.1

到目前爲止,我想我們把它搬到1.1中來使用也不是非常困難的事情。下面根據我的實踐結果來討論如何在Script Callback

首先介紹我第一次錯誤的使用方法。

根據2.0的思路,第一感覺就是我把它的那些系統生成的腳本,我自己給他挖掘出來,添加到客戶端,然後在後臺添加自己的GetCallbackReference(),並實現RaiseCallback()兩個方法,不就是一個1.1版本的Script Callback

首先我根據vs2005的簡單的msdn,以及跟蹤其返回值,寫了個假的GetCallbackReference();代碼如下:

 

protected string GetCallbackEventReference(System.Web.UI.Control control, string argument, string clientCallback, string context, string clientErrorCallback, bool useAsync)

       
{

           
string[] ReturnValue = new string[6];

           
if(control.ID != null)

              ReturnValue[
0= control.ID.ToString();

           
else

              ReturnValue[
0= "'__Page'";

 

           ReturnValue[
1= argument;

           ReturnValue[
2= clientCallback;

           

           ReturnValue[
3= context!=null?context:"null";

           ReturnValue[
4= clientErrorCallback!=null?clientErrorCallback:"null";

           ReturnValue[
5= "false";

           

           
return String.Format("WebForm_DoCallback({0})",String.Join(",",ReturnValue));

           

       }


 

protected string GetCallbackEventReference(System.Web.UI.Control control, string argument, string clientCallback, string context, string clientErrorCallback, bool useAsync)

       
{

           
string[] ReturnValue = new string[6];

           
if(control.ID != null)

              ReturnValue[
0= control.ID.ToString();

           
else

              ReturnValue[
0= "'__Page'";

 

           ReturnValue[
1= argument;

           ReturnValue[
2= clientCallback;

           

           ReturnValue[
3= context!=null?context:"null";

           ReturnValue[
4= clientErrorCallback!=null?clientErrorCallback:"null";

           ReturnValue[
5= "false";

           

           
return String.Format("WebForm_DoCallback({0})",String.Join(",",ReturnValue));

           

       }


 

本來想對其6個參數作詳細介紹的,可是考慮到這不是正確的方法,所以在此就不在敘述,如果想知道的朋友可以查看msdn2.library.com(這裏的還是舊版本),或者查看vs2005的對象瀏覽器。

類似2.0中在Page_Load作如下引用:

String callbackRef = this.GetCallbackEventReference(this,"document.all['DropDownList1'].value","MoreInfo",null,null,false);

btn.Attributes["onclick"] = String.Format("javascript:{0}",callbackRef);

 

並將我提供的的所有2.0中的系統腳本加到客戶端中,可是調試的時候確發現,我手工添加的腳本和服務端添加的腳本存在的區別就在於編譯的順序不一樣,當編譯客戶端的腳本的時候服務端的腳本還沒有生成,也就是說,它無法調用theFormpostUrl等變量,於是我想到,是不是可以在後臺在Page_Init的時候以編程的方式加入到客戶端,必須確保它是在服務端腳本加入後而執行的,至於放在Page_Init中還是在Page_PreRender()我不是很清楚。

好錯誤的方法討論到此,下面介紹作者的方法,也是正確的方法,起初我想用2.0中原有的腳本也許更強大,更完善。作者的方法很簡單。簡單的實現了xmlHTTP的客戶端與服務端的通信,但是不支持其它版本的瀏覽器。

後臺ScriptCallback.aspx.cs:

 public class ScriptCallback : System.Web.UI.Page

    
{

       
protected System.Web.UI.HtmlControls.HtmlButton btn;

       
protected System.Web.UI.WebControls.DropDownList DropDownList1;

       

       
private void Page_Load(object sender, System.EventArgs e)

       
{

           
if(IsCallback())

              
return;

           

           
if(!IsCallback())

              
this.PopulateList();

           

           
string callbackRef = "MoreInfo1()";

           btn.Attributes[
"onclick"= String.Format("javascript:{0}",callbackRef);

       }


       

       
private bool IsCallback()

       
{

           
if(Request.QueryString["Callback"!= null)

           
{

              
string param = Request.QueryString["param"].ToString();

              Response.Write(RaiseCallbackEvent(param));

              Response.Flush();

              Response.End();

              
return true;

           }


           
return false;

       }


 

       

       
private void PopulateList()

       
{

           DataProvider dp 
= new DataProvider();

           DropDownList1.DataTextField 
= "UserName";

           DropDownList1.DataValueField 
= "ID";

           DropDownList1.DataSource 
= dp.GetAllUserConfig().Tables[0];

           DropDownList1.DataBind();

       }


       
string RaiseCallbackEvent(string eventArgument)

       
{

           
string[] buf = new string[6];

           DataProvider dp 
= new DataProvider();

           DataTable dt 
= dp.GetAllUserConfig().Tables[0];

           DataRow[] dr 
=dt.Select("ID = " + eventArgument);

           buf[
0= dr[0]["ID"].ToString();

           buf[
1= dr[0]["UserName"].ToString();

           buf[
2= dr[0]["Password"].ToString();

           buf[
3= dr[0]["Authority"].ToString();

           buf[
4= dr[0]["BlogName"].ToString();

           buf[
5= dr[0]["Email"].ToString();

 

           
return String.Join(",", buf);

 

       }


 

   
前臺的腳本如下:

 public class ScriptCallback : System.Web.UI.Page

    
{

       
protected System.Web.UI.HtmlControls.HtmlButton btn;

       
protected System.Web.UI.WebControls.DropDownList DropDownList1;

       

       
private void Page_Load(object sender, System.EventArgs e)

       
{

           
if(IsCallback())

              
return;

           

           
if(!IsCallback())

              
this.PopulateList();

           

           
string callbackRef = "MoreInfo1()";

           btn.Attributes[
"onclick"= String.Format("javascript:{0}",callbackRef);

       }


       

       
private bool IsCallback()

       
{

           
if(Request.QueryString["Callback"!= null)

           
{

              
string param = Request.QueryString["param"].ToString();

              Response.Write(RaiseCallbackEvent(param));

              Response.Flush();

              Response.End();

              
return true;

           }


           
return false;

       }


 

       

       
private void PopulateList()

       
{

           DataProvider dp 
= new DataProvider();

           DropDownList1.DataTextField 
= "UserName";

           DropDownList1.DataValueField 
= "ID";

           DropDownList1.DataSource 
= dp.GetAllUserConfig().Tables[0];

           DropDownList1.DataBind();

       }


       
string RaiseCallbackEvent(string eventArgument)

       
{

           
string[] buf = new string[6];

           DataProvider dp 
= new DataProvider();

           DataTable dt 
= dp.GetAllUserConfig().Tables[0];

           DataRow[] dr 
=dt.Select("ID = " + eventArgument);

           buf[
0= dr[0]["ID"].ToString();

           buf[
1= dr[0]["UserName"].ToString();

           buf[
2= dr[0]["Password"].ToString();

           buf[
3= dr[0]["Authority"].ToString();

           buf[
4= dr[0]["BlogName"].ToString();

           buf[
5= dr[0]["Email"].ToString();

 

           
return String.Join(",", buf);

 

       }


 

   
前臺的腳本如下:


function MoreInfo1() 

    
var selectedID = document.all["DropDownList1"].value; 
    
var xml = DoCallback("ScriptCallback.aspx",selectedID); 
    
var o = xml.responseText.split(","); 
    e_ID.innerHTML 
= o[0]; 
    e_UserName.innerHTML 
= o[1]; 
    e_Password.innerHTML 
= o[2]; 
    e_Authority.innerHTML 
= o[3]; 
    e_BlogName.innerHTML 
= o[4]; 
    e_Email.innerHTML 
= o[5]; 

function DoCallback(url,params) 

    
var pageUrl = url + "?callback=true&param=" + params; 
    
var xmlRequest = new ActiveXObject("Microsoft.XMLHTTP"); 
    xmlRequest.open(
"POST",pageUrl,false); 
    xmlRequest.setRequestHeader(
"Content-Type""application/x-www-form-urlencoded"); 
    xmlRequest.send(
null); 
    
return xmlRequest; 
}


其中e_ID,e_UserName等類似分別是我呈現表格的第二列的cellID

function MoreInfo1() 

    
var selectedID = document.all["DropDownList1"].value; 
    
var xml = DoCallback("ScriptCallback.aspx",selectedID); 
    
var o = xml.responseText.split(","); 
    e_ID.innerHTML 
= o[0]; 
    e_UserName.innerHTML 
= o[1]; 
    e_Password.innerHTML 
= o[2]; 
    e_Authority.innerHTML 
= o[3]; 
    e_BlogName.innerHTML 
= o[4]; 
    e_Email.innerHTML 
= o[5]; 

function DoCallback(url,params) 

    
var pageUrl = url + "?callback=true&param=" + params; 
    
var xmlRequest = new ActiveXObject("Microsoft.XMLHTTP"); 
    xmlRequest.open(
"POST",pageUrl,false); 
    xmlRequest.setRequestHeader(
"Content-Type""application/x-www-form-urlencoded"); 
    xmlRequest.send(
null); 
    
return xmlRequest; 
}


其中e_ID,e_UserName等類似分別是我呈現表格的第二列的cellID

 

1.1中的效果如下:

 

 Figer4.JPG

 

 

至此我們實現了在ASP.NET1.1中的無postback的和服務端的提交獲取數據。原理就是利用了xmlHTTP。不過我們還是更期待在2.0中來使用該功能。

思考與問題

整個研究學習過程中,我逃避了兩點。第一,對2.0中的腳本程序沒有做細緻的分析,它到底是如何運行的,第二,如果我一定要用服務端的腳本,我如何通過後臺把腳本以程序方式加入到客戶端,並且在呈現客戶端頁面後再調用。如果你有興趣的話,可以和我一起研究哦。

個人覺得,在該文章上發佈的時候已近有人提出來這樣做的安全性,我覺得很有道理,如此所有的通信就相當於明碼在這樣傳來傳去,對於傳一些比較重要的數據的時候這樣做是很危險的,我也不是很清楚2.0中有沒有對這個問題提供其它可靠的有安全保障的方法。但如果把這個方法用在簡單的更具客戶的不同要求而時時地對頁面中某些元素進行驗證,少量的數據綁定,這可以算是一個不錯的解決方法!如果有大量數據要通過此方法和服務端通信,是不是可以加一個loading bar,讓更新數據部分的元素停止操作,而用戶仍然可以操作其它控件這樣的二次開發,我還沒有嘗試,我想不久就會嘗試。所以做gon功能簡單,要把功能做出漂亮的UI就很難,如果要在漂亮的UI上加上user experience就是難上加難啊!

作者信息

在此註冊blog一直沒有發表任何文章,我一直覺得自己水平還不夠,這次下了決心,參考msdn的文章,然後加上自己總結實踐,湊成了這篇文章,希望能給各位有所賞,有所析,有所用。小弟在此獻醜了,我想我以後主要還是這種方式來提交和大家一起學習進步。這樣我自己也能有很大收穫,也能給大家帶來一點內容。

關於我自己,我現在就讀杭州電子科技大學的通信工程學院,2005年就是大三下了,不知道這兒大學生多麼?希望能和各位交個朋友。

生活博客:http://spaces.msn.com/members/rbmnetatmsn/

常用Emailrbmxxx at hotmail.com

  

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章