探索AJAX中的消息傳輸模式 (上)
相關(guān)文章:探索AJAX中的消息傳輸模式 (下)
有這樣一個AJAX的應(yīng)用場合,提供一系列的標簽連接,讓用戶任意選擇,瀏覽器向服務(wù)器發(fā)送請求查詢得到想要的數(shù)據(jù)信息。下面就以這個應(yīng)用討論下消息傳輸。
一、普通的文本消息傳輸
建立一ASP.NET AJAX應(yīng)用程序,先為AJAXMessageText.aspx頁面做好簡單的布局準備,我們采用HyperLink控件做為導航連接,放置在一個table里,并設(shè)置一單元格作為數(shù)據(jù)顯示區(qū),設(shè)置其作為服務(wù)器控件運行(runat="server"),如下圖示:
各個控件的命名以數(shù)據(jù)顯示區(qū)的名稱如下:
<asp:HyperLink ID="hlAjax" runat="server" Text="AJAX" NavigateUrl="Java |
用戶通過點擊HyperLink控件,客戶端向服務(wù)器發(fā)送請求,返回的數(shù)據(jù)可能來自不同的地方(數(shù)據(jù)庫,XML,普通的文件.....),這里以Message類來封裝這些數(shù)據(jù),詳細代碼定義如下:
/// <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提供與服務(wù)器異步通信的能力,從而使用戶從請求/響應(yīng)的循環(huán)中解脫出來。"); str.Append("借助于Ajax,可以在用戶單擊按鈕時,使用JavaScript和DHTML立即更新UI,"); str.Append(" 并向服務(wù)器發(fā)出異步請求,以執(zhí)行更新或查詢數(shù)據(jù)庫。"); 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 和業(yè)界專家會晤。即時了解 Microsoft 許多令人驚喜的公告。"); ASPNET = str.ToString(); str = new StringBuilder(); str.Append("Castle是針對.NET平臺的一個開源項目,從數(shù)據(jù)訪問框架ORM到IOC容器,再到WEB層的MVC框架、AOP,"); str.Append("基本包括了整個開發(fā)過程中的所有東西,為我們快速的構(gòu)建企業(yè)級的應(yīng)用程序提供了很好的服務(wù)。"); CASTLE = str.ToString(); str = new StringBuilder(); str.Append("Web Service 是在 Internet 上進行分布式計算的基本構(gòu)造塊,是組件對象技術(shù)在 Internet 中的延伸,"); str.Append("是一種部署在 Web 上的組件。它融合了以組件為基礎(chǔ)的開發(fā)模式和 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應(yīng)用中,客戶端和服務(wù)器端進行數(shù)據(jù)通信絕大多數(shù)都是通過WebService來完成,這里我們?yōu)镸essage所類的數(shù)據(jù)方便了與客戶端交互提供一個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提供根據(jù)客戶端傳遞過來的參數(shù)返回Message類里所封裝的相應(yīng)數(shù)據(jù)。此時,我們就應(yīng)該著手客戶端請求的發(fā)送處理,在ASP.NET AJAX應(yīng)用里,我們可以很方便的通過ScriptManager引入WebService:
<asp:ScriptManager ID="ScriptManager1" runat="server"> <Services> <asp:ServiceReference Path="MessageWebService.asmx" /> </Services> </asp:ScriptManager> |
在客戶端,通過ASP.NET AJAX對JavaScript的擴展,我們可以很方便的得到各個控件的引用,以及調(diào)用WebService方法,設(shè)置回調(diào)函數(shù)來處理返回值,下面是客戶端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獲取數(shù)據(jù) MessageWebService.GetMessage(topic,onGetTextMessageCallback); } //回調(diào)函數(shù) 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對應(yīng)的字符傳是帶有css樣式及html標識的字符串,返回這個html字符串那客戶端是否能得到解析??答案是肯定的,這里只是做到了用戶點擊相應(yīng)的連接就發(fā)送請求到服務(wù)器,要使這個應(yīng)用完善,我們還得為這個應(yīng)用初始化一個顯示值:
public partial class AjaxMessageText : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { this.resultText.InnerHtml = new Message().AJAX; } } |
看看下面的運行結(jié)果:
#p#
二、復雜類型的消息傳輸
我們模擬一個數(shù)據(jù)庫查詢功能,根據(jù)客戶端的請求條件查詢數(shù)據(jù)庫,把查詢到的數(shù)據(jù)返回到客戶端顯示。這樣一個應(yīng)用一般來說可以通過XML來傳輸。ASPX頁面設(shè)計如下:
正如上圖所示,以MSSQL2000里的Northwind數(shù)據(jù)庫里的Employees表為例,根據(jù)客戶端的條件(排序字段,提取的記錄條數(shù))查詢數(shù)據(jù)庫,下面是數(shù)據(jù)庫訪問代碼:
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]; } }
數(shù)據(jù)庫訪問方法GetEmployees提供根據(jù)客戶傳遞的參數(shù)查詢Employees表里的數(shù)據(jù)并以DataTable的形式返回,到這里我們同上面一樣可以借助WebService來處理返回的DataTable,將數(shù)據(jù)處理為一個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應(yīng)用基本上都是應(yīng)用的一個模式,從發(fā)送請求--->響應(yīng)請求--->數(shù)據(jù)傳輸--->處理回調(diào)??蛻舳斯ぷ髁孔畲蟮木褪窃诨卣{(diào)函數(shù)里,下面是本示例的回調(diào)函數(shù)定義:
//回調(diào)函數(shù) 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'>"); //構(gòu)建表頭 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>"); //構(gòu)建數(shù)據(jù)行 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(); }
在客戶端的回調(diào)函數(shù)里,把服務(wù)器端返回的字符串解析為一個xml對象,通過JavaScript操作DOM將xml對象里的每一條數(shù)據(jù)解析后存入數(shù)組,隨后根據(jù)頁面上選擇要顯示字段動態(tài)構(gòu)造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里的示例數(shù)據(jù)庫Northwind里的Employees表為例<br /> 所要顯示的列 方式字段 提取記錄行數(shù)<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; //調(diào)用WebService獲取數(shù)據(jù) MessageWebService.GetEmployees(orderBy,maxRows,onXmlMessageCallback); } //回調(diào)函數(shù) 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'>"); //構(gòu)建表頭 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>"); //構(gòu)建數(shù)據(jù)行 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>
文章中有部分內(nèi)容我作了修改,在原文中加入了示例分析。希這篇文章對大家有所幫助,要更深入的學習AJAX是數(shù)據(jù)傳輸請查閱其他相關(guān)書籍或資料。歡迎大家拍磚指正,謝謝。
【編輯推薦】