相关文章:探索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是数据传输请查阅其他相关书籍或资料。欢迎大家拍砖指正,谢谢。
【编辑推荐】