探索AJAX中的消息傳輸模式 (下)
在上一篇《探索AJAX中的消息傳輸模式 (上)》一文中,我主要介紹了普通字符串(Plain-text string)和XML格式的傳輸模式,然而在實際的開發(fā)應(yīng)用中,這兩種方法基本上可以足夠應(yīng)付我們的需求了,不過在對于復(fù)雜的對象傳輸?shù)臅r候,采用上面所介紹的這兩種傳輸模式有點顯得不理想。于此,本文將結(jié)合《探索AJAX中的消息傳輸模式(一) 》再介紹一種輕量級的數(shù)據(jù)交換格式JSON(JavaScript Object Notation) ,這是一種JavaScrpt自己的一種用來描述對象的方法,JSON從某個角度看可以說是XML的替代品。
在怎么使用JSON來進(jìn)行數(shù)據(jù)傳輸之前,我們先來看看幾個簡單的JSON語法,為不熟悉JSON且想看本文的朋友打下基礎(chǔ)。JSON和XML一樣也是一種簡單文本格式。相對于XML,它更加易讀、更便于肉眼檢查。在語法的層面上,JSON與其他格式的區(qū)別是在于分隔數(shù)據(jù)的字符,JSON中的分隔符限于單引號、小括號、中括號、大括號、冒號和逗號。下面是一個JSON有效負(fù)載:
{"UserID":"0001","UserName":"ZhangSan","UserAge":"22"} |
看起來是不是很簡單,鍵與值一一對應(yīng)(Key----Value),下面我們看看一個復(fù)雜點的JSON有效負(fù)載:
{Employees:[ {"EmployeeID":"1","LastName":"Davolio","City":"Seattle","Country":"USA"}, {"EmployeeID":"2","LastName":"Fuller","City":"Tacoma","Country":"USA"} ] } |
從上面的JSON可以很清晰的看出,在Employees這個對象里包含有兩條數(shù)據(jù),我們將其用XML改寫,如下:
<?xml version='1.0' ?> <Employees> <Employee> <EmployeeID>1</EmployeeID> <LastName>Davolio</LastName> <City>Seattle</City> <Country>USA</Country> </Employee> <Employee> <EmployeeID>2</EmployeeID> <LastName>Fuller</LastName> <City>Tacoma</City> <Country>USA</Country> </Employee> <Employees> |
關(guān)于JSON更詳細(xì)的使用和語法格式請查看相關(guān)資料,這里我推薦一個網(wǎng)站(http://www.json.org/)。也可以在在園里搜索下園內(nèi)前輩們的文章,Truly的《深入淺出JSON 》這篇文章就介紹了JSON,個人感覺介紹的很細(xì)致。
上面說了這么多,我們還是用一個示例來演示下JSON的使用,要不就成了紙上談兵了。 本文的是《探索AJAX中的消息傳輸模式 (上)》的續(xù)篇,示例代碼還是建立在此文的基礎(chǔ)上,在WebService里添加一新方法提供根據(jù)員工編號(EmployeeID)查詢小于等于(<=)該編號的所用員工信息:
[WebMethod] public string GetEmployeeWithJson(int id) { //查詢出EmployeeID,LastName,City,Country四個字段 DataTable dt = DataAccess.GetEmployees(id); StringBuilder json = new StringBuilder(); json.Append("{Employees:["); int i = 0; string result = string.Empty; foreach (DataRow row in dt.Rows) { json.Append("{"); json.Append(@"""EmployeeID"":""" + row["EmployeeID"] + @""","); json.Append(@"""LastName"":""" + row["LastName"] + @""","); json.Append(@"""City"":""" + row["City"] + @""","); json.Append(@"""Country"":""" + row["Country"] + @"""}"); if (++i == dt.Rows.Count) { json.Append("}]"); } json.Append(","); } json.Append("}"); result = json.ToString().Remove(json.Length - 2, 1); //移除"," result = result.Remove(result.Length - 3, 1); //移除"}" return result; }
DataAccess.GetEmpoyees(int id)方法定義:
public static DataTable GetEmployees(int id) { string cmdText = "select EmployeeID,LastName,City,Country from Employees"; cmdText += " where EmployeeID <= " + id; return Exce(cmdText); //執(zhí)行SQL返回DataTable } |
這里也許大家會有所疑問,為什么這方法后面要移除一個","和"}",這是在上面動態(tài)構(gòu)造JSON字符串的時候多出來的,如果不移除方法的返回值則是下面這樣:
為了使在客戶端通過JavaScript能夠正確的解吸此JSON,在返回值后面多出的一個","和"}"是必須去掉的,如下:
到此,服務(wù)端的工作算準(zhǔn)備完畢,下面看看客戶端是如何實現(xiàn),首先為aspx頁面提供ScriptManager控件,然后引入WebService以便在客戶端調(diào)用WebService里的方法:
<asp:ScriptManager ID="ScriptManager1" runat="server"> <Services> <asp:ServiceReference Path="MessageWebService.asmx" /> </Services> </asp:ScriptManager> |
在提供一個下來列表控件來讓用戶選擇員工編號,這里通過設(shè)置默認(rèn)值(在實際開發(fā)應(yīng)用中可能會從數(shù)據(jù)庫里讀取數(shù)據(jù),這里只是為了做程序演示),通過一個按扭來發(fā)送請求,將結(jié)果顯示在div(resultEmployee)里:
請選擇員工編號范圍小于(<)<asp:DropDownList ID="ddlEmployeeID" runat="server"> <asp:ListItem>1</asp:ListItem> <asp:ListItem>2</asp:ListItem> <asp:ListItem>3</asp:ListItem> <asp:ListItem>4</asp:ListItem> <asp:ListItem>5</asp:ListItem> <asp:ListItem>6</asp:ListItem> <asp:ListItem>7</asp:ListItem> <asp:ListItem>8</asp:ListItem> </asp:DropDownList> <input id="Query" type="button" value="查 詢" /><br /><hr /> <div id="resultEmployee"></div> |
同樣,我們需要初始化客戶端對控件的引用,以及為按扭添加執(zhí)行事件:
var ddlEmployeeID; var divResult; var buttonQuery; function pageLoad() { ddlEmployeeID = $get("<% = ddlEmployeeID.ClientID %>"); divResult = $get("resultEmployee"); buttonQuery = $get("Query"); $addHandler(buttonQuery,"click",onButtonClicked); onButtonClicked(null); } |
當(dāng)點擊按扭的時候就觸發(fā)click事件,調(diào)用onButtonClicked方法,執(zhí)行調(diào)用WebService里的方法:
function onButtonClicked(eventElement) { //取得選擇的員工ID var employeeID = ddlEmployeeID.options[ddlEmployeeID.selectedIndex].value; //調(diào)用WebService獲取數(shù)據(jù) MessageWebService.GetEmployeeWithJson(employeeID,onJsonCallBack); } |
以異步的方式向服務(wù)端發(fā)起請求,把employeeID做為參數(shù)傳遞到服務(wù)器端,通過onJsonCallBack回調(diào)方法來處理返回的數(shù)據(jù),如下所示:
//根據(jù)返回的數(shù)據(jù)動態(tài)構(gòu)造html表格 var html = new Sys.StringBuilder(); html.append("<table width='460px' cellspacing='1' cellpadding='2' border='0' bgcolor='#999999'>"); html.append("<tr>"); html.append("<td bgcolor='gold' align='center'><b>EmployeeID</b></td>"); html.append("<td bgcolor='gold' align='center'><b>LastName</b></td>"); html.append("<td bgcolor='gold' align='center'><b>City</b></td>"); html.append("<td bgcolor='gold' align='center'><b>Country</b></td>"); html.append("</tr>"); for (var i=0;i< data.Employees.length;i++) { html.append("<tr>"); html.append("<td bgcolor='white'>"+data.Employees[i]["EmployeeID"]+"</td>"); html.append("<td bgcolor='white'>"+data.Employees[i].LastName+"</td>"); html.append("<td bgcolor='white'>"+data.Employees[i].City+"</td>"); html.append("<td bgcolor='white'>"+data.Employees[i].Country+"</td>"); html.append("</tr>"); } html.append("</table>"); resultEmployee.innerHTML = html.toString();
客戶端的完整代碼:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="AjaxMessageJson.aspx.cs" Inherits="AjaxMessageJson" %> <!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>無標(biāo)題頁</title> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server"> <Services> <asp:ServiceReference Path="MessageWebService.asmx" /> </Services> </asp:ScriptManager> <%--d--%> </div> 請選擇員工編號范圍小于(<)<asp:DropDownList ID="ddlEmployeeID" runat="server"> <asp:ListItem>1</asp:ListItem> <asp:ListItem>2</asp:ListItem> <asp:ListItem>3</asp:ListItem> <asp:ListItem>4</asp:ListItem> <asp:ListItem>5</asp:ListItem> <asp:ListItem>6</asp:ListItem> <asp:ListItem>7</asp:ListItem> <asp:ListItem>8</asp:ListItem> </asp:DropDownList> <input id="Query" type="button" value="查 詢" /><br /><hr /> <div id="resultEmployee"></div> </form> <script type="text/javascript"> var ddlEmployeeID; var divResult; var buttonQuery; function pageLoad() { ddlEmployeeID = $get("<% = ddlEmployeeID.ClientID %>"); divResult = $get("resultEmployee"); buttonQuery = $get("Query"); $addHandler(buttonQuery,"click",onButtonClicked); onButtonClicked(null); } function onButtonClicked(eventElement) { //取得選擇的員工ID var employeeID = ddlEmployeeID.options[ddlEmployeeID.selectedIndex].value; //調(diào)用WebService獲取數(shù)據(jù) MessageWebService.GetEmployeeWithJson(employeeID,onJsonCallBack); } function onJsonCallBack(text) { var data = eval("data="+text); //服務(wù)端的WebService返回的是一個JSON字符串,上面的賦值后data的數(shù)據(jù)實際就等同于下面的定義 //var data = {Employees:[{"EmployeeID":"1","LastName":"Davolio","City":"Seattle","Country":"USA"}, // {"EmployeeID":"2","LastName":"Fuller","City":"Tacoma","Country":"USA"}, // {"EmployeeID":"3","LastName":"Leverling","City":"Kirkland","Country":"USA"}]}; // //根據(jù)返回的數(shù)據(jù)動態(tài)構(gòu)造html表格 var html = new Sys.StringBuilder(); html.append("<table width='460px' cellspacing='1' cellpadding='2' border='0' bgcolor='#999999'>"); html.append("<tr>"); html.append("<td bgcolor='gold' align='center'><b>EmployeeID</b></td>"); html.append("<td bgcolor='gold' align='center'><b>LastName</b></td>"); html.append("<td bgcolor='gold' align='center'><b>City</b></td>"); html.append("<td bgcolor='gold' align='center'><b>Country</b></td>"); html.append("</tr>"); for (var i=0;i< data.Employees.length;i++) { html.append("<tr>"); html.append("<td bgcolor='white'>"+data.Employees[i]["EmployeeID"]+"</td>"); html.append("<td bgcolor='white'>"+data.Employees[i].LastName+"</td>"); html.append("<td bgcolor='white'>"+data.Employees[i].City+"</td>"); html.append("<td bgcolor='white'>"+data.Employees[i].Country+"</td>"); html.append("</tr>"); } html.append("</table>"); resultEmployee.innerHTML = html.toString(); } </script> </body> </html>
如上處理,如果服務(wù)器端無數(shù)據(jù)返回則在客戶端頁面上只輸出表頭信息。
如果有數(shù)據(jù)返回,則動態(tài)的構(gòu)造了表格并顯示在頁面上,如下:
【編輯推薦】