成人午夜激情影院,小视频免费在线观看,国产精品夜夜嗨,欧美日韩精品一区二区在线播放

用ASP.NET 2.0實現(xiàn)AJAX風格的Web開發(fā)

2010-08-28 10:48:44來源:西部e網(wǎng)作者:

  提要 在過去的幾個月中,基于AJAX技術(shù)開發(fā)高度交互的Web應(yīng)用程序的設(shè)計模式迅速流行開來。現(xiàn)在,具有高度可配置性的Web應(yīng)用程序,例如Google Maps和A9,都在綜合利用這些技術(shù)來創(chuàng)造豐富的客戶端用戶體驗。其實,結(jié)合AJAX技術(shù)進行Web開發(fā)并非最近的研究成果,只不過這些技術(shù)一直以來不斷得到持續(xù)更新和改進。

  本文中我有三個目的。首先,我想提供一個AJAX風格應(yīng)用程序的高級概述。其次,我想詳細地描述ASP.NET 2.0的異步回調(diào)機制。最后,我想對構(gòu)建AJAX風格應(yīng)用程序的工具和框架的未來改進作一下展望。

  歸納來看,AJAX風格的Web應(yīng)用程序展示了下列特征:

  · 到Web服務(wù)器的異步請求-在用戶等待來自于Web服務(wù)器的響應(yīng)時,瀏覽器用戶接口不會被堵塞,而是可以繼續(xù)響應(yīng)用戶的交互。

  · 高度依賴于用JavaScript編寫的基于瀏覽器的邏輯-W3C DOM的最新改進和標準化為實現(xiàn)動態(tài)的客戶端UI更新提供了支持。

  · 在瀏覽器和Web服務(wù)器之間的基于XML數(shù)據(jù)的交換-XMLHttp對象使得與Web服務(wù)器進行通訊而不需要重載頁面成為可能。

  一個AJAX應(yīng)用程序和傳統(tǒng)型Web應(yīng)用程序之間的最大差別是,每次用戶交互不會導(dǎo)致每一個HTTP請求都被發(fā)送到Web服務(wù)器;而是,用JavaScript實現(xiàn)的基于瀏覽器的邏輯掌握著控制權(quán),之后再由該控制決定是局部處理請求還是向服務(wù)器作異步調(diào)用。一旦到服務(wù)器的異步調(diào)用結(jié)束,客戶端邏輯立即適當更新UI的相關(guān)部分。這種方式具有下列優(yōu)點:

  · 用戶體驗更為豐富。例如,當一個Google地圖用戶沿一個方向拖動地圖時,系統(tǒng)就會在后臺向服務(wù)器發(fā)出一個異步請求,結(jié)果是他能夠在超出屏幕邊界后繼續(xù)拖動。這樣以來,當用戶進一步拖動地圖時,新的圖像已經(jīng)可用了。這導(dǎo)致一種響應(yīng)更快的感覺。

  · 既然跨越基于XMLHttp的到服務(wù)器的調(diào)用狀態(tài)并沒有丟失,那么,AJAX應(yīng)用程序就可以避免每次都重新生成UI界面。

  · 更多的邏輯位于瀏覽器端,從而減少了到Web服務(wù)器的來回請求的數(shù)量,進而全面改進系統(tǒng)的潛力。

  盡管存在這么多的優(yōu)點,然而AJAX風格的應(yīng)用程序還是存在一些不足之處。例如,AJAX風格應(yīng)用程序的開發(fā)是比較困難的,因為缺乏相應(yīng)的框架(一組類似于Windows MFC工具包的UI類)和IDE(調(diào)試,可視化設(shè)計,等等)支持。另外,基于AJAX進行開發(fā)要求一個人必須至少掌握兩種語言(DHTML和JavaScript)。而且,AJAX風格應(yīng)用程序的編碼需要更長的時間,因為它需要另外的測試以使其支持多瀏覽器版本和類型。最后,由于基于JavaScript的源碼為終端用戶可存取,所以開發(fā)過程中的安全分析也變得非常重要。

  幸好,例如Atlas,AJAX.NET和Google Maps API等工具的出現(xiàn)為將來構(gòu)建AJAX風格的應(yīng)用程序提供了更好的支持。接下來,我們將討論一下,對于構(gòu)建AJAX風格應(yīng)用程序的支持技術(shù)的發(fā)展歷程以及我們能夠從最新發(fā)布的工具集Atlas得到怎樣的期望。

  讓我們首先討論XMLHttp對象。這個對象最初為微軟所引入,以后在其它平臺(包括Mozilla和蘋果公司的Safari瀏覽器)上也得到實現(xiàn)。XMLHttp支持到Web服務(wù)器的異步請求,這樣可以允許客戶端基于JavaScript邏輯調(diào)用Web服務(wù)器而不需要重載整個頁面。

  換句話說,在后臺與Web服務(wù)器的交互而不引起整個頁面重載是完全有可能的。

  至于XMLHttp對象的使用則相當直接。為簡單起見,讓我們僅考慮IE特定的語法。其實,XMLHttp在其它瀏覽器上的實現(xiàn)語法與這里的討論也很類似。

request = new ActiveXObject("Microsoft.XMLHTTP");
if (request){ request.onreadystatechange = CallbackHandler;
 request.open("GET", URL, true);
 request.send();
}
function CallbackHandler(){
 if ((request.readyState == 4) && (request.status == 200){
  string response = request.responseXML;
  //更新UI的相關(guān)部分
 }
}


  在上面的代碼片斷中,第一步實現(xiàn)實例化Microsoft.XMLHttp類。第二步設(shè)置我們剛剛創(chuàng)建的XMLHttp實例的屬性,其中包括當XMLHttp請求完成時將得到控制的回調(diào)函數(shù)的地址。因為我們在向服務(wù)器作異步調(diào)用(通過把open方法的第三個參數(shù)設(shè)置為true來實現(xiàn)),所以我們需要回調(diào)函數(shù)的地址。在回調(diào)函數(shù)實現(xiàn)過程中,我們作額外的檢查以確保完成請求。

  你從上面的示例代碼中可以看出,以獨立方式使用XMLHttp對象是相當簡單的。然而,把XMLHttp集成到HttpPage生命周期的其它部分中是比較困難的-例如,如何確保服務(wù)器端的方法調(diào)用能夠存取頁面中其它控件的狀態(tài)呢?為了正確初始化這些控件的狀態(tài),服務(wù)器端的回調(diào)處理需要經(jīng)歷一個與回調(diào)過程類似的HttpPage生命周期。直接使用XMLHttp對象的其它挑戰(zhàn)是,作為開發(fā)者,我們需要考慮不同的瀏覽器類型。幸好,ASP.NET 2.0提供了一個可重用的模式-它能夠使得存取回調(diào)功能非常容易。注意,隨同ASP.NET 2.0一同發(fā)行了若干控件,包括GridView,TreeView等,都綜合利用了回調(diào)機制。

  讓我們先看一下服務(wù)器端實現(xiàn)原理。首先,在服務(wù)器端要定義一個新的接口IcallBackEventHandler。任何ASPX頁面(或打算支持客戶端回調(diào)的控件)都需要實現(xiàn)這個ICallBackEventHandler接口。ICallBackEventHandler接口定義了一個稱為RaiseCallbackEvent的方法。這個方法使用一個字符串類型的參數(shù)并且返回一個字符串。

  在客戶端,為了初始化回調(diào)功能,需要調(diào)用一個特殊的JavaScript函數(shù)。你可以通過調(diào)用ClientScriptManager.GetCallbackEventReference來獲得一個到這個特殊的JavaScript函數(shù)的引用。到GetCallbackEventReference的調(diào)用將產(chǎn)生一個回調(diào)引用。當調(diào)用此回調(diào)函數(shù)時,你只需要傳遞一個字符串類型的參數(shù)。這是與服務(wù)器端的RaiseCallbackEvent簽名一致的。這就是你在客戶端建立回調(diào)機制所需做的一切。其它的把客戶端回調(diào)函數(shù)鉤(hook up)到服務(wù)器端的IcallBackEventHandler接口的RaiseCallbackEvent方法的實現(xiàn)則是由框架來完成的。前面提到的初始化回調(diào)機制的特殊JavaScript函數(shù)使用了另外兩個參數(shù)(__CALLBACKPARAM和__CALLBACKID)作為回饋數(shù)據(jù),它們分別代表傳遞到調(diào)用者的字符串參數(shù)和控件的ID。在服務(wù)器端,ASP.NET檢測其它兩個參數(shù)的存在并且會把請求路由到適當?shù)目丶@將導(dǎo)致調(diào)用目標控件上的RaiseCallbackEvent方法。為了解決前面提到的頁面上的控件的初始化問題,ASP.NET運行時刻在服務(wù)一次回調(diào)時提供了一個簡化版本的HttpPage生命周期。這一周期包括瀏覽頁面初始化的某個具體階段,觀察狀態(tài)加載,頁面加載和回調(diào)函數(shù)事件處理等。一旦回調(diào)函數(shù)事件被控件所處理,HttpPage生命周期的其它階段就會被跳過。

  為了幫助更好地理解ASP.NET 2.0的回調(diào)機制,發(fā)行包中包括了一個簡單的進度條控件,它依靠回調(diào)來決定服務(wù)器確定的一項任務(wù)的狀態(tài)。下面的列表1顯示了該ProgressBar控件的代碼。為了支持客戶端回調(diào)函數(shù),這個控件實現(xiàn)了ICallbackEventHandler接口。為了演示之目的,RaiseCallbackEvent方法實現(xiàn)簡單地查找存儲在會話中的一個計數(shù)器,每次給計數(shù)器加1,并且把新值返回到客戶端。最后,列表2顯示了負責初始化該回調(diào)函數(shù)的JavaScript代碼。它使用了this.Page.ClientScript.GetCallbackEventReference來獲得一個到需要初始化回調(diào)的函數(shù)的安全引用。

  列表1:ProgressBar.cs

public class ProgressBar : System.Web.UI.Control, System.Web.UI.ICallbackEventHandler{
private int PercentCompleted{
 get
 {
  if System.Web.HttpContext.Current.Session["PercentComplete"] == null) {
   System.Web.HttpContext.Current.Session["PercentComplete"] = 1;
 } 
 else {
  System.Web.HttpContext.Current.Session["PercentComplete"] =(int)System.Web.HttpContext.Current.Session["PercentComplete"] + 1;
 }
 return (int)System.Web.HttpContext.Current.Session["PercentComplete"];
}
set
{
 System.Web.HttpContext.Current.Session["PercentComplete"] = 1;
}
}
public string RaiseCallbackEvent(string eventArguments) {
 int percent = this.PercentCompleted;
 if (percent > 100)
 {
  this.PercentCompleted = 1;
  return "completed";
 }
 else
 {
  return percent.ToString() + "%";
 }
}
protected override void OnPreRender(EventArgs e) {
 this.Page.ClientScript.RegisterClientScriptBlock(typeof(ProgressBar),
"ProgressBar", this.GetClientSideScript(), true);
 base.OnPreRender(e);
}
protected override void Render(HtmlTextWriter writer) {
 System.Text.StringBuilder sb = new StringBuilder();
 sb.Append(@"<table id=""ProgressBarContainer"" bgcolor=""LightSteelBlue""
 border=""0"" width=""400"" style=""DISPLAY:none; POSITION: absolute;
 Z-INDEX: 10"">");
 sb.Append(@"<tr><td colspan=""3"" style=""padding:3px 2px 2px 10px"">");
 sb.Append(@"<font face=""Verdana, Arial, Helvetica, sans-serif"" size=""2"">");
 sb.Append(@"<span id=""ProgressBarLabel"">Uploading...</span>");
 sb.Append(@"</font></td></tr><tr><td>");
 sb.Append(@"<font size=""1""> </font></td><td bgcolor=""#999999""
 width=""100%"">");
 sb.Append(@"<table id=""ProgressBar"" border=""0"" width=""0""
 cellspacing=""0"">");
 sb.Append(@"<tr><td style=""background-image:url(progressbar.gif)"">
 <font size=""1""> </font></td>");
 sb.Append(@"</tr></table></td>");
 sb.Append(@"<td><font size=""1""> </font></td></tr>");
 sb.Append(@"<tr height=""5px""><td colspan=""3""></td></tr>");
 sb.Append(@"</table>");
 writer.Write(sb.ToString());
 base.Render(writer);
}
private string GetClientSideScript() {
 System.Reflection.Assembly dll =
 System.Reflection.Assembly.GetExecutingAssembly();
 StreamReader reader;
 reader = new StreamReader(dll.GetManifestResourceStream("ProgressBar.txt"));
 StringBuilder js = new StringBuilder(reader.ReadToEnd());
 string fp = this.Page.ClientScript.GetCallbackEventReference(this, "", "UpdateProgressBar", "");
 js.Replace("##InitiateCallBack##", fp);
 reader.Close();
 return js.ToString();
}
}

  列表2:ProgressBar.js

<script language="javascript">
var isCompleted=false;
//這個函數(shù)初始化到服務(wù)器端的回調(diào)
function DrawProgressBar(){
 ##InitiateCallBack##;
 if (!isCompleted) {
  window.setTimeout('DrawProgressBar()',200);
 }
 else
 {
  isCompleted=false;
  document.getElementById("ProgressBarContainer").style.display = 'none';
 }
}
//當thecallback完成時,下列函數(shù)被調(diào)用
function UpdateProgressBar(percent){
 if (percent == 'completed'){
  isCompleted=true;
 }
 else{
  document.getElementById("ProgressBar").width = percent;
 }
}

  通過使用在ASP.NET 2.0提供的客戶端回調(diào)函數(shù),實現(xiàn)進度條控件是比較直接的,因為在控件和客戶端之間傳遞的數(shù)據(jù)僅是一個簡單的字符串。然而,一旦我們把其它數(shù)據(jù)類型也添加到其中,我們就遇到在JavaScript和.NET類型系統(tǒng)之間不匹配的問題。遺憾的是,ASP.NET 2.0中的回調(diào)函數(shù)實現(xiàn)對此并無多大幫助。任何想使用多種數(shù)據(jù)類型(簡單類型和復(fù)雜類型)的應(yīng)用程序,都要實現(xiàn)一種自己的定制模式。

  幸好,這種限制能夠通過使用一個AJAX.NET開源庫來加以克服,AJAX.NET實現(xiàn)了一種基于代理的方式來調(diào)用服務(wù)器端函數(shù)。AJAX.NET定義了一種稱為AJAXMethod的定制屬性。當一個服務(wù)器端方法用AJAXMethod加以修飾時,一個基于JavaScript的客戶端代理將被HttpHandler(它是AJAX.NET庫的一部分)自動生成。不同于ASP.NET 2.0,它支持單個參數(shù)的字符串類型以便用于回調(diào)實現(xiàn)。AJAX.NET支持整數(shù),字符串,雙精度數(shù),DateTime,DataSet等多種類型。

  Bertrand Le Roy建議使用AJAX.NET來處理JavaScript和.NET類型系統(tǒng)之間的差別。他創(chuàng)建了一種稱為EcmaScriptObject的服務(wù)器端控件-它基于.NET技術(shù)重新創(chuàng)建了JavaScript類型系統(tǒng)。其想法是,用.NET重新生成一種客戶端對象圖。當轉(zhuǎn)換發(fā)生在服務(wù)器端時,這種方法顯得更有意義。

  即使我們有了一種類型安全的方法來調(diào)用回調(diào)函數(shù),但是,我們還面臨其它的挑戰(zhàn)。JavaScript擔當起了把AJAX應(yīng)用程序的各個部分組合到一起的"膠水"的作用。當然,相應(yīng)地,對JavaScript的依賴性也進一步增加。遺憾的是,盡管JavaScript是一種強有力且通用的語言,但是它并沒有實現(xiàn)面向?qū)ο蟮脑瓌t。這意味著,要實現(xiàn)代碼重用可能更為困難。當然,可以使用一些技巧來使JavaScript看上去更象傳統(tǒng)的面向?qū)ο笳Z言。不過即使如此,要實現(xiàn)托管語言中的例如事件和代理等特征仍然相當困難。

  其它困難還包括:缺乏一個可重用框架來進一步提高JavaScript的開發(fā)效率。如果有一種基于JavaScript的能夠隱蔽不同執(zhí)行環(huán)境區(qū)別的UI框架或許更好些。另外,如果能夠創(chuàng)建一組類,它們可以用一種安全的方式(相對于手工編碼SOAP包并使用XMLHttp來傳遞它們)來調(diào)用Web服務(wù),也會相當不錯。

  最近來自微軟的Atlas工程許諾要重點解決這類問題。這是一種極大程度地簡化AJAX風格開發(fā)的偉大嘗試。Atlas提供了一種新的JavaScript框架(注意,下面是基于微軟的一次初步宣布,以后有可能發(fā)生改變)-UI開發(fā)工具包。這其中包括:支持諸如拖放和數(shù)據(jù)綁定等特征的常用控件;調(diào)用Web服務(wù)的SOAP棧;隱蔽瀏覽器差別的瀏覽器兼容層;包括例如本地緩沖等內(nèi)容的客戶端構(gòu)建模塊。另外,ASP.NET團隊還計劃為ASP.NET開發(fā)其它構(gòu)建模塊,例如配置管理,成員管理等,以便把它們用作Web服務(wù)端點,從而實現(xiàn)可以直接從JavaScript中對Web服務(wù)進行存取-例如可以容易地從客戶端存取個人信息。最后,Atlas工程還計劃擴展JavaScript語法以便包括接口、生命周期管理和multicast事件。

  據(jù)說,接下來的幾個月將是令A(yù)JAX開發(fā)者激動的日子。因此,我非常希望本文能夠激起您對AJAX的興趣,并在你以后構(gòu)建下一代Web應(yīng)用程序時優(yōu)先考慮使用這一技術(shù)。

 

關(guān)鍵詞:ASP.NETAJAX

贊助商鏈接:

主站蜘蛛池模板: 基隆市| 丰原市| 深水埗区| 志丹县| 原平市| 遂溪县| 嘉荫县| 肇东市| 福建省| 土默特右旗| 耒阳市| 枣庄市| 克什克腾旗| 缙云县| 澎湖县| 富裕县| 姜堰市| 阳朔县| 饶河县| 临颍县| 西吉县| 抚松县| 虞城县| 稻城县| 佛坪县| 名山县| 双峰县| 南召县| 抚州市| 红河县| 鄄城县| 佛山市| 韩城市| 庆城县| 广水市| 葫芦岛市| 乌鲁木齐市| 靖西县| 渝北区| 长子县| 花垣县|