探索AJAX中的消息傳輸模式 (上)
相關文章:探索AJAX中的消息傳輸模式 (下)
有這樣一個AJAX的應用場合,提供一系列的標簽連接,讓用戶任意選擇,瀏覽器向服務器發送請求查詢得到想要的數據信息。下面就以這個應用討論下消息傳輸。
一、普通的文本消息傳輸
建立一ASP.NET AJAX應用程序,先為AJAXMessageText.aspx頁面做好簡單的布局準備,我們采用HyperLink控件做為導航連接,放置在一個table里,并設置一單元格作為數據顯示區,設置其作為服務器控件運行(runat="server"),如下圖示:

各個控件的命名以數據顯示區的名稱如下:
<asp:HyperLink ID="hlAjax" runat="server" Text="AJAX" NavigateUrl="Java |
用戶通過點擊HyperLink控件,客戶端向服務器發送請求,返回的數據可能來自不同的地方(數據庫,XML,普通的文件.....),這里以Message類來封裝這些數據,詳細代碼定義如下:
/// <summary>
/// Message 的摘要說明
/// </summary>
public class Message
{
public string AJAX=string.Empty;
public string ASPNET=string.Empty;
public string CASTLE=string.Empty;
public string WEBSERVICE=string.Empty;
public string HTML = string.Empty;
StringBuilder str = null;
public Message()
{
str = new StringBuilder();
str.Append("Ajax提供與服務器異步通信的能力,從而使用戶從請求/響應的循環中解脫出來。");
str.Append("借助于Ajax,可以在用戶單擊按鈕時,使用JavaScript和DHTML立即更新UI,");
str.Append(" 并向服務器發出異步請求,以執行更新或查詢數據庫。");
AJAX = str.ToString();
str = new StringBuilder();
str.Append("Microsoft 的 ASP.NET 和 Visual Studio 組將出席于曼德勒海灣度假舉行的 ASP.NET Connections 會議。");
str.Append("請參加深入而前沿的 ASP.NET、Visual Studio & .NET、SQL 和 Mobile Connections 交流會并同與會的");
str.Append("Microsoft 和業界專家會晤。即時了解 Microsoft 許多令人驚喜的公告。");
ASPNET = str.ToString();
str = new StringBuilder();
str.Append("Castle是針對.NET平臺的一個開源項目,從數據訪問框架ORM到IOC容器,再到WEB層的MVC框架、AOP,");
str.Append("基本包括了整個開發過程中的所有東西,為我們快速的構建企業級的應用程序提供了很好的服務。");
CASTLE = str.ToString();
str = new StringBuilder();
str.Append("Web Service 是在 Internet 上進行分布式計算的基本構造塊,是組件對象技術在 Internet 中的延伸,");
str.Append("是一種部署在 Web 上的組件。它融合了以組件為基礎的開發模式和 Web 的出色性能。");
WEBSERVICE = str.ToString();
str = new StringBuilder();
str.Append("<span style="+"font-weight:bold;font-size:20;color:Red;>");
str.Append("帶有HTML的字符串,返回此字符串,所擁有的樣式等都可以得到解析!");
str.Append("</span>");
HTML = str.ToString();
}
}
在ASP.NET AJAX應用中,客戶端和服務器端進行數據通信絕大多數都是通過WebService來完成,這里我們為Message所類的數據方便了與客戶端交互提供一個WebService:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class MessageWebService : System.Web.Services.WebService {
public MessageWebService () { }
[WebMethod]
public string GetMessage(string text)
{
Message message = new Message();
string str = string.Empty;
switch (text)
{
case "AJAX": str = message.AJAX; break;
case "ASPNET": str = message.ASPNET; break;
case "CASTLE": str = message.CASTLE; break;
case "SERVER": str = message.WEBSERVICE; break;
case "HTML": str = message.HTML; break;
}
return str;
}
}
方法GetMessage提供根據客戶端傳遞過來的參數返回Message類里所封裝的相應數據。此時,我們就應該著手客戶端請求的發送處理,在ASP.NET AJAX應用里,我們可以很方便的通過ScriptManager引入WebService:
<asp:ScriptManager ID="ScriptManager1" runat="server"> <Services> <asp:ServiceReference Path="MessageWebService.asmx" /> </Services> </asp:ScriptManager> |
在客戶端,通過ASP.NET AJAX對JavaScript的擴展,我們可以很方便的得到各個控件的引用,以及調用WebService方法,設置回調函數來處理返回值,下面是客戶端JS的完整代碼:
<script type="text/javascript">
var hlAjax;
var hlAspnet;
var hlCastle;
var hlService;
var hlHtml;
var resultText;
//初始化控件引用及事件
function pageLoad()
{
hlAjax = $get("<% =hlAjax.ClientID %>");
hlAspnet = $get("<% =hlAspnet.ClientID %>");
hlCastle = $get("<% =hlCastle.ClientID %>");
hlService = $get("<% =hlService.ClientID %>")
hlHtml = $get("<% = hlHtml.ClientID %>");
$addHandler(hlAjax,"click",onClick);
$addHandler(hlAspnet,"click",onClick);
$addHandler(hlCastle,"click",onClick);
$addHandler(hlService,"click",onClick);
$addHandler(hlHtml,"click",onClick);
resultText = $get("<% = resultText.ClientID %>");
}
function onClick(eventElement)
{
var topic = false;
switch(eventElement.target.id)
{
case hlAjax.id:topic = "AJAX";break;
case hlAspnet.id:topic = "ASPNET";break;
case hlCastle.id:topic = "CASTLE";break;
case hlService.id:topic = "SERVER";break;
case hlHtml.id:topic = "HTML";break;
}
//引用WebService獲取數據
MessageWebService.GetMessage(topic,onGetTextMessageCallback);
}
//回調函數
function onGetTextMessageCallback(text)
{
resultText.innerHTML=text;
}
</script>
上述中,通過AJAX所提供的$get()方法獲取到各控件的客戶端引用,并通過$addHandler()方法為其添加了客戶端事件,注意有個HTML的連接,這里我們追逐到Message類里:
str = new StringBuilder();
str.Append("<span style="+"font-weight:bold;font-size:20;color:Red;>");
str.Append("帶有HTML的字符串,返回此字符串,所擁有的樣式等都可以得到解析!");
str.Append("</span>");
HTML = str.ToString();
|
類里所封裝的html對應的字符傳是帶有css樣式及html標識的字符串,返回這個html字符串那客戶端是否能得到解析??答案是肯定的,這里只是做到了用戶點擊相應的連接就發送請求到服務器,要使這個應用完善,我們還得為這個應用初始化一個顯示值:
public partial class AjaxMessageText : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
this.resultText.InnerHtml = new Message().AJAX;
}
}
|
看看下面的運行結果:

#p#
二、復雜類型的消息傳輸
我們模擬一個數據庫查詢功能,根據客戶端的請求條件查詢數據庫,把查詢到的數據返回到客戶端顯示。這樣一個應用一般來說可以通過XML來傳輸。ASPX頁面設計如下:

正如上圖所示,以MSSQL2000里的Northwind數據庫里的Employees表為例,根據客戶端的條件(排序字段,提取的記錄條數)查詢數據庫,下面是數據庫訪問代碼:
public class DataAccess
{
private static string strCon = "Data Source=.;database=northwind;uid=sa;pwd=;";
public DataAccess()
{
}
public static DataTable GetEmployees(string orderBy, int maxRows)
{
string cmdText = "select top " + maxRows;
cmdText += " EmployeeID,LastName,City,Country ";
cmdText += "from Employees order by " + orderBy;
return Exce(cmdText);
}
private static DataTable Exce(string cmdText)
{
SqlConnection conn = new SqlConnection(strCon);
SqlDataAdapter sda = new SqlDataAdapter(cmdText, conn);
DataSet ds = new DataSet();
sda.Fill(ds);
return ds.Tables[0];
}
}
數據庫訪問方法GetEmployees提供根據客戶傳遞的參數查詢Employees表里的數據并以DataTable的形式返回,到這里我們同上面一樣可以借助WebService來處理返回的DataTable,將數據處理為一個XML字符串返回到客戶端:
[WebMethod]
public string GetEmployees(string orderBy, int manxRows)
{
DataTable dt = DataAccess.GetEmployees(orderBy, manxRows);
StringBuilder xml = new StringBuilder();
xml.Append("<?xml version='1.0' ?>");
xml.Append("<Employees>");
foreach (DataRow row in dt.Rows)
{
string id = row["EmployeeID"].ToString();
string name = row["LastName"].ToString();
string city = row["City"].ToString();
string country = row["Country"].ToString();
xml.Append("<Employee>");
xml.Append("<EmployeeID>" + id + "</EmployeeID>");
xml.Append("<LastName>" + name + "</LastName>");
xml.Append("<City>" + city + "</City>");
xml.Append("<Country>" + country + "</Country>");
xml.Append("</Employee>");
}
xml.Append("</Employees>");
return xml.ToString();
}
在客戶端的處理程序上,大致和上面的普通的文本消息差不多,其實整個AJAX應用基本上都是應用的一個模式,從發送請求--->響應請求--->數據傳輸--->處理回調。客戶端工作量最大的就是在回調函數里,下面是本示例的回調函數定義:
//回調函數
function onXmlMessageCallback(result)
{
var xml;
if(window.ActiveXObject) //IE
{
xml = new ActiveXObject("Microsoft.XMLDOM");
xml.async = false;
xml.loadXML(result);
}
else
{
var parser = new DOMParser();
xml = parser.parseFromString(result,"text/xml");
}
var employees = xml.getElementsByTagName("Employee");
var html = new Sys.StringBuilder();
html.append("<table width='500px' cellspacing='1' cellpadding='0' border='0' bgcolor='#999999'>");
//構建表頭
html.append("<tr>");
if(cbID.checked)
html.append("<td bgcolor='lightblue'><b>ID</b></td>");
if(cbLastName.checked)
html.append("<td bgcolor='lightblue'><b>LastName</b></td>");
if(cbCity.checked)
html.append("<td bgcolor='lightblue'><b>City</b></td>");
if(cbCountry.checked)
html.append("<td bgcolor='lightblue'><b>Country</b></td>");
html.append("<tr>");
//構建數據行
for (var i=0; i<employees.length;i++)
{
html.append("<tr>");
if(cbID.checked)
{
var id= employees[i].getElementsByTagName("EmployeeID")[0].childNodes[0].nodeValue;
html.append("<td>"+id+"</td>");
}
if(cbLastName.checked)
{
var LastName= employees[i].getElementsByTagName("LastName")[0].childNodes[0].nodeValue;
html.append("<td>"+LastName+"</td>");
}
if(cbCity.checked)
{
var City= employees[i].getElementsByTagName("City")[0].childNodes[0].nodeValue;
html.append("<td>"+City+"</td>");
}
if(cbCountry.checked)
{
var Country= employees[i].getElementsByTagName("Country")[0].childNodes[0].nodeValue;
html.append("<td>"+Country+"</td>");
}
html.append("</tr>");
}
html.append("</table>");
resultXml.innerHTML=html.toString();
}
在客戶端的回調函數里,把服務器端返回的字符串解析為一個xml對象,通過JavaScript操作DOM將xml對象里的每一條數據解析后存入數組,隨后根據頁面上選擇要顯示字段動態構造html代碼并顯示在指定的位置(resutlXml)。 下面是客戶端的完整代碼:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="AjaxMessageXML.aspx.cs" Inherits="AjaxMessageXML" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>無標題頁</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="MessageWebService.asmx" />
</Services>
</asp:ScriptManager>
以MSSQL 2000里的示例數據庫Northwind里的Employees表為例<br />
所要顯示的列
方式字段 提取記錄行數<br />
<asp:CheckBox ID="cbID" runat="server" Text="ID" />
<asp:CheckBox ID="cbLastName" runat="server" Text="LastName" />
<asp:CheckBox ID="cbCity" runat="server" Text="City" />
<asp:CheckBox ID="cbCountry" runat="server" Text="Country" />
<asp:DropDownList ID="ddlOrder" runat="server">
<asp:ListItem Value="EmployeeID" Text="ID"></asp:ListItem>
<asp:ListItem Value="LastName" Text="LastName"></asp:ListItem>
<asp:ListItem Value="City" Text="City"></asp:ListItem>
<asp:ListItem Value="Country" Text="Country"></asp:ListItem>
</asp:DropDownList>
<asp:DropDownList ID="ddlRows" runat="server">
<asp:ListItem>1</asp:ListItem>
<asp:ListItem>2</asp:ListItem>
<asp:ListItem>3</asp:ListItem>
<asp:ListItem>5</asp:ListItem>
<asp:ListItem>8</asp:ListItem>
<asp:ListItem>10</asp:ListItem>
</asp:DropDownList>
<input id="buttonGO" style="width: 53px" type="button" value="GO" />
<hr />
<div id="resultXml"></div>
<script type="text/javascript">
var cbID;
var cbLastName;
var cbCity;
var cbCountry;
var ddlOrder;
var ddlRows;
var resultXml;
var buttonGO;
//初始化控件引用及事件
function pageLoad()
{
cbID = $get("<% =cbID.ClientID %>");
cbLastName = $get("<% =cbLastName.ClientID %>");
cbCity = $get("<% =cbCity.ClientID %>");
cbCountry = $get("<% =cbCountry.ClientID %>");
ddlOrder = $get("<% =ddlOrder.ClientID %>");
ddlRows = $get("<% =ddlRows.ClientID %>");
resultXml = $get("resultXml");
buttonGO = $get("buttonGO");
$addHandler(buttonGO,"click",onButtonClicked);
onButtonClicked(null);
}
function onButtonClicked(eventElement)
{
if(!cbID.checked && !cbLastName.checked && cbCity.checked && cbCountry.checked)
{
alert("至少選擇一列!");
return;
}
var orderBy = ddlOrder.options[ddlOrder.selectedIndex].value;
var maxRows = ddlRows.options[ddlRows.selectedIndex].value;
//調用WebService獲取數據
MessageWebService.GetEmployees(orderBy,maxRows,onXmlMessageCallback);
}
//回調函數
function onXmlMessageCallback(result)
{
var xml;
if(window.ActiveXObject) //IE
{
xml = new ActiveXObject("Microsoft.XMLDOM");
xml.async = false;
xml.loadXML(result);
}
else
{
var parser = new DOMParser();
xml = parser.parseFromString(result,"text/xml");
}
var employees = xml.getElementsByTagName("Employee");
var html = new Sys.StringBuilder();
html.append("<table width='500px' cellspacing='1' cellpadding='0' border='0' bgcolor='#999999'>");
//構建表頭
html.append("<tr>");
if(cbID.checked)
html.append("<td bgcolor='lightblue'><b>ID</b></td>");
if(cbLastName.checked)
html.append("<td bgcolor='lightblue'><b>LastName</b></td>");
if(cbCity.checked)
html.append("<td bgcolor='lightblue'><b>City</b></td>");
if(cbCountry.checked)
html.append("<td bgcolor='lightblue'><b>Country</b></td>");
html.append("<tr>");
//構建數據行
for (var i=0; i<employees.length;i++)
{
html.append("<tr>");
if(cbID.checked)
{
var id= employees[i].getElementsByTagName("EmployeeID")[0].childNodes[0].nodeValue;
html.append("<td>"+id+"</td>");
}
if(cbLastName.checked)
{
var LastName= employees[i].getElementsByTagName("LastName")[0].childNodes[0].nodeValue;
html.append("<td>"+LastName+"</td>");
}
if(cbCity.checked)
{
var City= employees[i].getElementsByTagName("City")[0].childNodes[0].nodeValue;
html.append("<td>"+City+"</td>");
}
if(cbCountry.checked)
{
var Country= employees[i].getElementsByTagName("Country")[0].childNodes[0].nodeValue;
html.append("<td>"+Country+"</td>");
}
html.append("</tr>");
}
html.append("</table>");
resultXml.innerHTML=html.toString();
}
</script>
</form>
</body>
</html>

文章中有部分內容我作了修改,在原文中加入了示例分析。希這篇文章對大家有所幫助,要更深入的學習AJAX是數據傳輸請查閱其他相關書籍或資料。歡迎大家拍磚指正,謝謝。
【編輯推薦】

























