一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

在ASP.NET中實現(xiàn)AJAX

 老莊走狗 2005-12-05

2005.10.28  來自:MSDN  Karl Seguin

Asynchronous JavaScript and XMLAJAX)最近掀起的高潮,要完全歸功于GoogleGoogle SuggestGoogle Maps中的使用。對ASP.NET而言,AJAX不需要回傳就能進(jìn)行服務(wù)器端處理,從而使客戶機(jī)(瀏覽器)具有豐富的服務(wù)器端能力。換句話說,它為異步指派和處理請求與服務(wù)器響應(yīng)提供了一個框架。AJAX利用了一些不是很新穎的已有技術(shù),但是對這些技術(shù)(加到一起就是AJAX)的愛好最近突然升溫。

請嘗試Michael Schwarz的AJAX .NET包裝器,通過它ASP.NET開發(fā)人員可以快速方便的部署很容易利用AJAX功能的頁面。需要注意的是,這個包裝器處于初期開發(fā)階段,因此還沒有完全成熟。

然而,AJAX這樣的技術(shù)很可能破壞分層體系結(jié)構(gòu)(N-Tier)。我的看法是,AJAX增加了表示邏輯層(甚至更糟,業(yè)務(wù)層)滲透到表示層的可能性。像我這樣嚴(yán)肅的架構(gòu)師對這種想法可能畏步不前。我感到AJAX的使用即便稍微越過了層次邊界,這種代價也是值得深思的。當(dāng)然,這要視具體的項目和環(huán)境而定。

起步

它是如何工作的——概述

AJAX依靠代理(broker)指派和處理往返服務(wù)器的請求。對此,.NET包裝器依靠客戶端XmlHttpRequest對象。多數(shù)瀏覽器都支持XmlHttpRequest對象,這就是選擇它的原因。因為包裝器的目的是隱藏XmlHttpRequest的實現(xiàn),我們就不再詳細(xì)討論它了。

包裝器本身通過將.NET函數(shù)標(biāo)記為AJAX方法來工作。標(biāo)記之后,AJAX就創(chuàng)建對應(yīng)的JavaScript函數(shù),這些函數(shù)(和任何JavaScript函數(shù)一樣)作為代理可以在客戶端使用XmlHttpRequest調(diào)用。這些代理再映射回服務(wù)器端函數(shù)。

復(fù)雜嗎?并不復(fù)雜。我們來看一個例子。假設(shè)有一個.NET函數(shù):

ublic int Add(int firstNumber, int secondNumber)
{
 
return firstNumber + secondNumber;
}

AJAX .NET包裝器將自動創(chuàng)建名為“Add”、帶有兩個參數(shù)的JavaScript函數(shù)。使用JavaScript(在客戶機(jī)上)調(diào)用該函數(shù)時,請求將傳遞給服務(wù)器并把結(jié)果返回給客戶機(jī)。

初始設(shè)置

我們首先介紹“安裝”項目中使用的.dll的步驟。如果您很清楚如何添加.dll文件引用,可以跳過這一節(jié)。

首先,如果還沒有的話,請下載最新的AJAX版本。解壓下載的文件并把ajax.dll放到項目的引用文件夾中。在Visual Studio.NET中有機(jī)Solution Explorer的“References(引用)”節(jié)點并選擇Add Reference(添加引用)。在打開的對話框中,單擊Browse(瀏覽)并找到ref/ajax.dll文件。依次單擊Open(打開)和Ok(確認(rèn))。這樣就可以用AJAX .NET包裝器編程了。

建立HttpHandler

為了保證正常工作,第一步是在web.config中設(shè)置包裝器的HttpHandler。不需要詳細(xì)解釋HttpHandlers是什么及其如何工作,只要知道它們用于處理ASP.NET請求就足夠了。比如,所有*.aspx頁面請求都由System.Web.UI.PageHandlerFactory類處理。類似的,我們讓所有對ajax/*.ashx的請求由Ajax.PageHandlerFactory處理:

<configuration>
 
<system.web>
   
<httpHandlers>
     
<add verb="POST,GET" path=" ajax/*.ashx"
         
type="Ajax.PageHandlerFactory, Ajax" />
    </httpHandlers> 

   
...
 
<system.web>
</configuration>

簡言之,上面的代碼告訴ASP.NET,和指定路徑(ajax/*.ashx)匹配的任何請求都由Ajax.PageHandlerFactory而不是默認(rèn)處理程序工廠來處理。不需要創(chuàng)建ajax子目錄,使用這個神秘的目錄只是為了讓其他HttpHandlers能夠在自己建立的子目錄中使用.ashx擴(kuò)展。

建立頁面

現(xiàn)在我們可以開始編碼了。創(chuàng)建一個新頁面或者打開已有的頁面,在file后的代碼中,為Page_Load事件添加以下代碼:

public class Index : System.Web.UI.Page{
 
private void Page_Load(object sender, EventArgs e){
      Ajax.Utility.RegisterTypeForAjax(typeof(Index));     

      //...   

 
}
  //... 

}

調(diào)用RegisterTypeForAjax將在頁面上引發(fā)后面的JavaScript(或者在頁面中手工加入以下兩行代碼):

<script language="javascript" src="ajax/common.ashx"></script>
<script language="javascript"
src="ajax/Namespace.PageClass, AssemblyName.ashx"></script>

其中最后一行的含義是:

下面是AjaxPlay項目中sample.aspx頁面的結(jié)果例子:

<%@ Page Inherits="AjaxPlay.Sample" Codebehind="sample.aspx.cs" ... %>
<html>
<head>
 
<script language="javascript" src="ajax/common.ashx"></script>
 
<script language="javascript"
         
src="ajax/AjaxPlay.Sample,AjaxPlay.ashx"></script>
</head>
  <body>   

   
<form id="Form1" method="post" runat="server">
     
...
    </form>   

 
</body>
</html>

可以在瀏覽器中手工導(dǎo)航到src路徑(查看源代碼,復(fù)制粘貼路徑)檢查是否一切正常。如果兩個路徑都輸出一些(似乎)毫無意義的文本,就萬事大吉了。如果什么也沒輸出或者出現(xiàn)ASP.NET錯誤,則表明有些地方出現(xiàn)問題。

即便不知道HttpHandlers如何工作,上面的例子也很容易理解。通過web.config,我們已經(jīng)保證所有對ajax/*.ashx的請求都由自定義的處理程序處理。顯然,這里的兩個腳本標(biāo)簽將由自定義的處理程序處理。

創(chuàng)建服務(wù)器端函數(shù)

現(xiàn)在來創(chuàng)建可從客戶端調(diào)用中異步訪問的服務(wù)器端函數(shù)。因為目前還不支持所有的返回類型(不用擔(dān)心,將在目前的基礎(chǔ)上開發(fā)新的版本),我們繼續(xù)使用簡單的ServerSideAdd函數(shù)吧。在file后的代碼中,向頁面添加下列代碼:

[Ajax.AjaxMethod()]
public int ServerSideAdd(int firstNumber, int secondNumber)
{
 
return firstNumber + secondNumber;
}

要注意,這些函數(shù)具有Ajax.AjaxMethod屬性集。該屬性告訴包裝器這些方法創(chuàng)建javaScript代理,以便在客戶端調(diào)用。

客戶端調(diào)用

最后一步是用JavaScript調(diào)用該函數(shù)。AJAX包裝器負(fù)責(zé)創(chuàng)建帶有兩個參數(shù)的JavaScript函數(shù)Sample.ServerSideAdd。對這種最簡單的函數(shù),只需要調(diào)用該方法并傳遞兩個數(shù)字:

<%@ Page Inherits="AjaxPlay.Sample" Codebehind="sample.aspx.cs" ... %>
<html>
<head>
 
<script language="javascript" src="ajax/common.ashx"></script>
 
<script language="javascript"
         
src="ajax/AjaxPlay.Sample,AjaxPlay.ashx"></script>
</head>
  <body>   

   
<form id="Form1" method="post" runat="server">
     
<script language="javascript">
       
var response = Sample.ServerSideAdd(100,99);
       
alert(response.value);
     
</script>
    </form>   

 
</body>
</html>

當(dāng)然,我們不希望僅僅用這種強(qiáng)大的能力來警告用戶。這就是所有客戶端代理(如JavaScript Sample.ServerSideAd函數(shù))還接受其他特性的原因。這種特性就是為了處理響應(yīng)而調(diào)用的回調(diào)函數(shù):

Sample.ServerSideAdd(100,99, ServerSideAdd_CallBack);

function ServerSideAdd_CallBack(response){
 
if (response.error != null){
 
alert(response.error);
 
return;
 
}
 
alert(response.value);
}

從上述代碼中可以看到我們指定了另外一個參數(shù)。ServerSideAdd_CallBack(同樣參見上述代碼)是用于處理服務(wù)器響應(yīng)的客戶端函數(shù)。這個回調(diào)函數(shù)接收一個響應(yīng)對象,該對象公開了三個主要性質(zhì)

  • Value——服務(wù)器端函數(shù)實際返回的值(無論是字符串、自定義對象還是數(shù)據(jù)集)。
  • Error——錯誤消息,如果有的話。
  • Request——xml http請求的原始響應(yīng)。
  • Context——上下文對象。

首先我們檢查error只看看是否出現(xiàn)了錯誤。通過在服務(wù)器端函數(shù)中拋出異常,可以很容易處理error特性。在這個簡化的例子中,然后用這個值警告用戶。Request特性可用于獲得更多信息(參見下一節(jié))。

處理類型

返回復(fù)雜類型

Ajax包裝器不僅能處理ServerSideAdd函數(shù)所返回的整數(shù)。它目前還支持integersstrings、double、booleans、DateTimeDataSetsDataTables,以及自定義類和數(shù)組等基本類型。其他所有類型都返回它們的ToString值。

返回的DataSets和真正的.NET DataSet差不多。假設(shè)一個服務(wù)器端函數(shù)返回DataSet,我們可以通過下面的代碼在客戶端顯示其中的內(nèi)容:

<script language="JavaScript">
//Asynchronous call to the mythical "GetDataSet" server-side function
function getDataSet(){
  AjaxFunctions.GetDataSet(GetDataSet_callback);   

}
function GetDataSet_callback(response){
 
var ds = response.value;
 
if(ds != null && typeof(ds) == "object" && ds.Tables != null){
   
var s = new Array();
   
s[s.length] = "<table border=1>";
   
for(var i=0; i<ds.Tables[0].Rows.length; i++){
     
s[s.length] = "<tr>";
     
s[s.length] = "<td>" + ds.Tables[0].Rows[i].FirstName + "</td>";
     
s[s.length] = "<td>" + ds.Tables[0].Rows[i].Birthday + "</td>";
     
s[s.length] = "</tr>";
   
}
   
s[s.length] = "</table>";
   
tableDisplay.innerHTML = s.join("");
 
}
 
else {
   
alert("Error. [3001] " + response.request.responseText);
 
}
}
</script>

Ajax還可以返回自定義類,唯一的要求是必須用Serializable屬性標(biāo)記。假設(shè)有如下的類:

[Serializable()]
public class User{
 
private int _userId;
 
private string _firstName;
 
private string _lastName;

 
public int userId{
   
get { return _userId; }
 
}
 
public string FirstName{
   
get { return _firstName; }
 
}
 
public string LastName{
   
get { return _lastName; }
 
}
 
public User(int _userId, string _firstName, string _lastName){
   
this._userId = _userId;
   
this._firstName = _firstName;
   
this._lastName = _lastName;
 
}
 
public User(){}
 
[AjaxMethod()]
 
public static User GetUser(int userId){
   
//Replace this with a DB hit or something :)
   
return new User(userId,"Michael", "Schwarz");
 
}
}

我們可以通過調(diào)用RegisterTypeForAjax注冊GetUser代理:

private void Page_Load(object sender, EventArgs e){
 
Utility.RegisterTypeForAjax(typeof(User));
}

這樣就可以在客戶端異步調(diào)用GetUser

<script language="javascript">
function getUser(userId){
 
User.GetUser(GetUser_callback);
}
function GetUser_callback(response){
 
if (response != null && response.value != null){
   
var user = response.value;
    if (typeof(user) == "object"){         

     
alert(user.FirstName + " " + user.LastName);
   
}
 
}
}
getUser(1);
</script>

響應(yīng)中返回的值實際上是一個對象,公開了和服務(wù)器端對象相同的屬性(FirstNameLastNameUserId)。

自定義轉(zhuǎn)換器

我們已經(jīng)看到,Ajax .NET包裝器能夠處理很多不同的.NET類型。但是除了大量.NET類和內(nèi)建類型以外,包裝器對不能正確返回的其他類型僅僅調(diào)用ToString()。為了避免這種情況,Ajax .NET包裝器允許開發(fā)人員創(chuàng)建對象轉(zhuǎn)換器,用于在服務(wù)器和客戶機(jī)之間平滑傳遞復(fù)雜對象。

其他事項

在其他類中注冊函數(shù)

上面的例子中,我們的服務(wù)器端函數(shù)都放在執(zhí)行頁面背后的代碼中。但是,沒有理由不能把這些函數(shù)放在單獨的類文件中。要記住,包裝器的工作方式是在指定類中發(fā)現(xiàn)所有帶Ajax.AjaxMethod的方法。需要的類通過第二個腳本標(biāo)簽指定。使用Ajax.Utility.RegisterTypeForAjax,我們可以指定需要的任何類。比如,將我們的服務(wù)器端函數(shù)作為單獨的類是合情合理的:

Public Class AjaxFunctions
 
<Ajax.AjaxMethod()> _
 
Public Function Validate(username As String, password As String) As Boolean
   
‘do something
   
‘Return something
 
End Function
End Class

通過指定類的類型而不是頁面就可以讓Ajax包裝器創(chuàng)建代理:

private void Page_Load(object sender, EventArgs e){
 
Ajax.Utility.RegisterTypeForAjax(typeof(AjaxFunctions));
 
//...
}

要記住,客戶端代理的名稱是<ClassName>.<ServerSideFunctionName> 。因此,如果ServerSideAdd函數(shù)放在上面虛構(gòu)的AjaxFunctions類中,客戶端調(diào)用就應(yīng)該是: AjaxFunctions.ServerSideAdd(1,2) 。

代理到底是如何工作的

Ajax工具生成的第二個腳本標(biāo)簽(也可以手工插入)傳遞了頁面的名稱空間、類名和程序集。根據(jù)這些信息,Ajax.PageHandlerFactory就能夠使用反射得到具有特定屬性的任何函數(shù)的詳細(xì)信息。顯然,處理函數(shù)查找具有AjaxMethod屬性的函數(shù)并得到它們的簽名(返回類型、名稱和參數(shù)),從能夠創(chuàng)建必要的客戶端代理。具體而言,包裝器創(chuàng)建一個和類同名的JavaScript對象,該對象提供代理。換句話說,給定一個帶有Ajax ServerSideAdd方法的服務(wù)器端類AjaxFunctions,我們就會得到公開ServerSideAdd函數(shù)的AjaxFunction JavaScript對象。如果將瀏覽器指向第二個腳本標(biāo)簽的路徑就會看到這種動作。

返回Unicode字符

Ajax .NET包裝器能夠從服務(wù)器向客戶機(jī)返回Unicode字符。為此,數(shù)據(jù)在返回之前必須在服務(wù)器上用html編碼。比如:

[Ajax.AjaxMethod]
public string Test1(string name, string email, string comment){
 
string html = "";
 
html += "Hello " + name + "<br>";
 
html += "Thank you for your comment <b>";
 
html += System.Web.HttpUtility.HtmlEncode(comment);
 
html += "</b>.";
 
return html;
}

SessionState

服務(wù)器端函數(shù)中很可能需要訪問會話信息。為此,只需要通過傳遞給Ajax.AjaxMethod屬性的一個參數(shù)告訴Ajax啟用這種功能。

在考察包裝器會話能力的同時,我們來看看其他幾個特性。這個例子中我們有一個文檔管理系統(tǒng),用戶編輯的時候會對文檔加鎖。其他用戶可以請求在文檔可用的時候得到通知。如果沒有AJAX,我們就只能等待該用戶再次返回來檢查請求的文檔是否可用。顯然不夠理想。使用支持會話狀態(tài)的Ajax就非常簡單了。

首先來編寫服務(wù)器端函數(shù),目標(biāo)是循環(huán)遍歷用戶希望編輯的documentId(保存在會話中)并返回所有已釋放的文檔。

[Ajax.AjaxMethod(HttpSessionStateRequirement.Read)]
public ArrayList DocumentReleased(){
 
if (HttpContext.Current.Session["DocumentsWaiting"] == null){
   
return null;
 
}
 
ArrayList readyDocuments = new ArrayList();
 
int[] documents = (int[])HttpContext.Current.Session["DocumentsWaiting"];
 
for (int i = 0; i < documents.Length; ++i){
   
Document document = Document.GetDocumentById(documents[i]);
   
if (document != null && document.Status == DocumentStatus.Ready){
     
readyDocuments.Add(document);
    }       

 
}
 
return readyDocuments;
 
}
}

要注意,我們指定了HttpSessionStateRequirement.Read值(還可以用WriteReadWrite)。

現(xiàn)在編寫使用該方法的JavaScript

<script language="javascript">
function DocumentsReady_CallBack(response){
 
if (response.error != null){
   
alert(response.error);
   
return;
 
}
 
if (response.value != null && response.value.length > 0){
   
var div = document.getElementById("status");
   
div.innerHTML = "The following documents are ready!<br />";
   
for (var i = 0; i < response.value.length; ++i){
     
div.innerHTML += "<a href=\"edit.aspx?documentId=" + response.value[i].DocumentId + "\">" + response.value[i].Name + "</a><br />";
    }     

 
}
 
setTimeout(‘page.DocumentReleased(DocumentsReady_CallBack)‘, 10000);
}
</script>
 

<body onload="setTimeout(‘Document.DocumentReleased(DocumentsReady_CallBack)‘, 10000);">

我們的服務(wù)器端函數(shù)在頁面加載時調(diào)用一次,然后每隔10秒鐘調(diào)用一次?;卣{(diào)函數(shù)檢查響應(yīng)看看是否有返回值,有的話則在div標(biāo)簽中顯示該用戶可使用的新文檔。

結(jié)束語

AJAX技術(shù)已經(jīng)催生了原來只有桌面開發(fā)才具備的健壯而豐富的Web界面。Ajax .NET包裝器讓您很容易就能利用這種新的強(qiáng)大技術(shù)。請注意,Ajax .NET包裝器和文檔仍在開發(fā)之中。

引用通告地址 (0):
復(fù)制引用通告地址http://www./article/5403/trackback
復(fù)制引用通告地址http://www./article/5403/trackback/GB

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    国内真实露脸偷拍视频| 东北老熟妇全程露脸被内射| 欧美在线视频一区观看| 欧美一级日韩中文字幕| 亚洲中文字幕综合网在线| 日韩欧美国产精品自拍| 中文字幕在线五月婷婷| 国产原创中文av在线播放| 黄片免费观看一区二区| 亚洲国产精品一区二区| 亚洲最新一区二区三区| 免费黄色一区二区三区| 91亚洲国产成人久久| 亚洲中文字幕人妻系列| 日本少妇三级三级三级| 我要看日本黄色小视频| 亚洲五月婷婷中文字幕| 国产高清三级视频在线观看| 小黄片大全欧美一区二区| 国产免费黄片一区二区| 国产毛片不卡视频在线| 午夜国产福利在线播放| 一区二区免费视频中文乱码国产| 超薄丝袜足一区二区三区| 日本久久中文字幕免费| 国产成人免费高潮激情电| 久久国产精品亚州精品毛片 | 亚洲综合激情另类专区老铁性| 亚洲精品国产主播一区| 九九九热在线免费视频| 女同伦理国产精品久久久| 成人精品国产亚洲av久久| 免费性欧美重口味黄色| 免费在线成人激情视频| 一区二区三区欧美高清| 日韩欧美国产三级在线观看| 欧美日韩乱一区二区三区| 91精品国自产拍老熟女露脸| 亚洲精品小视频在线观看| 日本免费一本一二区三区| 国产高清精品福利私拍|