使用ASP.NET AJAX異步調用Web Service和頁面中的類方法(9):服務器端和客戶端數據類型的自動轉換:DataTable和DataSet

http://www.cnblogs.com/dflying/archive/2007/06/15/784053.html 

 

本文來自《ASP.NET AJAX程序設計 第II卷:客戶端Microsoft AJAX Library相關》的第三章《異步調用Web Service和頁面中的類方法》,請同時參考本章的其他文章

 

3.7.6 DataTableDataSet

DataTable和DataSet是ADO.NET中的重要概念,這兩個對象均非常複雜,其中包含了大量的複雜類型和循環引用。爲了能夠在 ASP.NET AJAX異步通訊層中傳遞這兩種類型的數據,微軟公司在ASP.NET AJAX Futures CTP版本中給出了自定義的DataTable和DataSet轉換方案——即藉助於ASP.NET AJAX強大的可擴展性,通過自定義JavaScriptConverter實現DataTable和DataSet類型的客戶端/服務器端自動轉換。

參考:在某些情況下,我們也需要通過編寫自定義的JavaScriptConverter來爲實際項目中遇到的某些複雜類型給出自定義的轉換方案。關於JavaScriptConverter組件的基本知識,請參考第2章;關於自定義JavaScriptConverter的編寫方法,將在第III 卷中介紹。

若想在ASP.NET AJAX異步通訊層中傳遞DataTable和DataSet這兩種類型的數據,首先我們應該確保安裝了ASP.NET AJAX的Futures CTP部分(關於對ASP.NET AJAX的Futures CTP部分的介紹以及安裝方法,請參考第I卷),並在Web站點中添加了對Microsoft.Web.Preview.dll程序集的引用(將該程序集拷貝到Web站點的/bin文件夾下),如圖3-31所示。

圖3-31在Web站點中添加對Microsoft.Web.Preview.dll程序集的引用

隨後讓我們在web.config文件中啓用ASP.NET AJAX Futures CTP中自帶的DataTable和DataSet相關JavaScriptConverter組件。將如下代碼添加至<configuration />/<system.web.extensions />/<scripting />/<webServices />節中:

<jsonSerialization>
  <converters>
      <add name="DataSetConverter" type="Microsoft.Web.Preview.Script.Serialization.Converters.DataSetConverter, Microsoft.Web.Preview, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      <add name="DataRowConverter" type="Microsoft.Web.Preview.Script.Serialization.Converters.DataRowConverter, Microsoft.Web.Preview, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      <add name="DataTableConverter" type="Microsoft.Web.Preview.Script.Serialization.Converters.DataTableConverter, Microsoft.Web.Preview, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
  </converters>
</jsonSerialization>

進行上述配置之後,我們即可ASP.NET AJAX異步通訊層中傳遞DataTable和DataSet了,讓我們通過一個實例程序說明具體的使用方法。

在本示例程序,我們將通過ASP.NET AJAX異步通訊層從服務器端Web Service方法中取得一個DataTable,並將其中的數據顯示爲頁面中的一個HTML <table />。首先從Web Service開始,代碼如下,注意不要忘記爲該Web Service類添加[System.Web.Script.Services.ScriptService]屬性:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class DataService : System.Web.Services.WebService
{
    [WebMethod]
    public DataTable GetDataTable(string tableName)
    {
        // 設定DataTable的名稱
        DataTable table = new DataTable(tableName);
        
        // 爲該DataTable添加兩列
        table.Columns.Add(new DataColumn("Id", typeof(int)));
        table.Columns.Add(new DataColumn("Name", typeof(string)));
 
        // 添加5行
        for (int i = 0; i < 5; ++i)
        {
            DataRow newRow = table.NewRow();
            newRow["Id"] = i;
            newRow["Name"] = string.Format("name {0}", i);
 
            table.Rows.Add(newRow);
        }
 
        return table;
    }
}

然後再客戶端ASP.NET頁面中添加ScriptManager控件,並引入該Web Service:

<asp:ScriptManager ID="sm" runat="server">
    <Services>
        <asp:ServiceReference Path="Services/DataService.asmx" />
    </Services>
</asp:ScriptManager>

來到頁面的UI部分:添加一個用來出發對服務器端Web Service方法的異步調用的按鈕和一個用來顯示由服務器端返回值構造出的HTML <table />的<div />:

<input id="btnGetDataTable" type="button" value="Get DataTable" 
    onclick="return btnGetDataTable_onclick()" />
<div id="result">
</div>

btnGetDataTable按鈕的click事件的處理函數定義如下:

function btnGetDataTable_onclick() {
    DataService.GetDataTable("My Table", onSucceeded);
}

此時,如果一切順利的話,在回調函數onSucceeded()中我們已經可以看到服務器端返回的DataTable的基本結構了。比如下面的代碼就使用Sys.Debug.traceDump()方法(關於Sys.Debug.traceDump()方法,請參考第1章中的介紹)查看了 result對象的詳細結構:

function onSucceeded(result) {
    Sys.Debug.traceDump(result);
}

在Visual Studio的“Output”窗口中,我們即可看到該客戶端DataTable的完整結構以及其中所包含的數據,如圖3-32所示。

圖3-32 客戶端DataTable的完整結構以及其中所包含的數據

當然,在Visual Studio的調試器中,我們也可以直接查看該DataTable的結構和數據,如圖3-33所示。

圖3-33 服務器端DataTable類型在客戶端的結構

從圖3-32和圖3-33可以看到,ASP.NET AJAX異步通訊層爲服務器端DataTable生成的客戶端JavaScript相應類型還是比較簡單的,很多原始DataTable中的數據之間的關係和約束均沒有保留下來。不過在一般的開發場景中,這些信息已經足夠滿足我們的使用需求了——畢竟,DataTable中的所有“數據”都絲毫不差地保留了下來。

參考:ASP.NET AJAX在Futures CTP版本中提供了更爲完備的客戶端DataTable類型,其完全限定名爲Sys.Preview.Data.DataTable。有關該類型的詳細介紹,請參考本書8.2.2節。

接下來讓我們回到該示例程序的編寫中來,完成回調函數onSucceeded(),將該客戶端DataTable中的數據以HTML <table />的形式顯示出來。完成後的回調函數onSucceeded()代碼如下,其中代碼流程均有詳細註釋,這裏不贅:

function onSucceeded(result) {
    // 測試
    //Sys.Debug.traceDump(result);
    //debugger;
    
    // 得到兩列的名稱
    var idColName = result.columns[0].name;
    var nameColName = result.columns[1].name;
    
    // 得到DataTable中的行集合
    var rows = result.rows;
    
    // 創建表格頭
    var builder = new Sys.StringBuilder("<table border=1>");
    builder.append(
        String.format(
            "<tr><td>{0}</td><td>{1}</td></tr>",
            idColName,
            nameColName
        )
    );
    
    // 創建表格內容
    for (var rowIndex = 0; rowIndex < rows.length; ++ rowIndex) {
        builder.append(
            String.format(
                "<tr><td>{0}</td><td>{1}</td></tr>",
                rows[rowIndex][idColName],
                rows[rowIndex][nameColName]
            )
        );
    }
    
    builder.append("</table>");
    
    // 顯示錶格
    $get("result").innerHTML = builder.toString();
}

至此,我們已經完成了本示例程序的編寫。運行該程序並點擊“Get DataTable”按鈕,將看到如圖3-34所示的界面。

圖3-34 從服務器端取得DataTable對象並顯示在頁面中

若是想得到DataSet對象,那麼ASP.NET AJAX異步通訊層也有着不錯的支持。在上面的DataService Web Service類中再添加如下一個方法:

[WebMethod]
public DataSet GetDataSet(string[] tableNames)
{
    DataSet dataSet = new DataSet();
    
    // 根據傳入的DataTable名稱創建各個DataTable
    for (int i = 0; i < tableNames.Length; ++i)
    {
        dataSet.Tables.Add(GetDataTable(tableNames[i]));
    }
    
    return dataSet;
}

該方法接受一個字符串數組,並根據該數組的長度創建相應個數的DataTable,然後將這些DataTable打包到一個DataSet中返回給客戶端。

在客戶端,我們可以使用如下JavaScript調用該Web Service方法:

var dataTableNames = ["My Table 1", "My Table 2", "My Table 3"];
DataService.GetDataSet(dataTableNames, onSucceeded);

在onSucceeded()回調函數中,返回的客戶端DataSet在Visual Studio調試器中顯示出的結構如圖3-35所示,可以看到該DataSet包含了3個DataTable對象。

圖3-35服務器端DataSet類型在客戶端的結構

雖然這個客戶端版本的DataSet仍舊比較簡單,但一般來講,這樣的數據結構已經足夠我們使用了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章