随笔-312  评论-12034  文章-2  trackbacks-256
本文来自《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仍旧比较简单,但一般来讲,这样的数据结构已经足够我们使用了。

posted on 2007-06-15 00:09 Dflying Chen 阅读(6197) 评论(33)  编辑 收藏 网摘 所属分类: ASP.NET AJAX (Atlas)

评论:
#1楼 2007-06-15 00:33 | 若寒      
沙发,哈!
原来有这个函数:Sys.Debug.traceDump(result);真是太有用了,谢谢Dflying!!

  回复  引用  查看    
#2楼[楼主] 2007-06-15 08:26 | Dflying Chen      
@若寒
不客气

  回复  引用  查看    
#3楼 2007-06-15 08:38 | VRC289[未注册用户]
最好能从第一章开始贴一点出来,让我们在书没出之前看一下。顺便问一下,第二卷什么时候出版?
  回复  引用    
#4楼[楼主] 2007-06-15 08:49 | Dflying Chen      
@VRC289
会逐渐添加一些内容的,不过第一章一般比较没意思阿,呵呵:)
争取在七月份出版

  回复  引用  查看    
#5楼 2007-06-15 08:58 | Cindy[未注册用户]
morning...
  回复  引用    
#6楼[楼主] 2007-06-15 09:00 | Dflying Chen      
@Cindy
morning...

  回复  引用  查看    
#7楼 2007-06-15 09:25 | Cat Chen      
应该说清楚是哪一个版本的ASP.NET Futures吧,因为日后的CTP可能还会变。
  回复  引用  查看    
#8楼[楼主] 2007-06-15 09:29 | Dflying Chen      
@Cat Chen
日后这部分功能很可能移动到核心版本中……那变化就更大了,呵呵

  回复  引用  查看    
#9楼 2007-06-15 12:36 | Anthan      
每天都有新的收获,学习中...
客户端可有构造DataTable或者DataSet传回服务器端吗?

  回复  引用  查看    
#10楼[楼主] 2007-06-15 15:33 | Dflying Chen      
@Anthan
可以阿,new一下就好了

  回复  引用  查看    
#11楼 2007-06-15 17:56 | 龙之子[未注册用户]
这个评论,完全没有价值嘛!
  回复  引用    
#12楼 2007-06-15 20:54 | yangli      
一直不太清楚Microsoft.Web.Preview.dll这个有什么用,能不能介绍一下?或是告诉我哪里有相关介绍的呢?
  回复  引用  查看    
#13楼 2007-06-15 21:25 | Anthan      
@Dflying Chen
直接用JavaScript在客户端构造一个类似于DataTable的对象传到服务器端去就可以了嘛?不用自己显示的对他进行转化嘛?
有例子否?还是在你书上,第二卷?

  回复  引用  查看    
#14楼[楼主] 2007-06-15 21:25 | Dflying Chen      
@yangli
这个帖子里面http://www.cnblogs.com/dflying/archive/2007/05/18/751741.html" target="_new">http://www.cnblogs.com/dflying/archive/2007/05/18/751741.html

7-10章就是Microsoft.Web.Preview.dll的用处

  回复  引用  查看    
#15楼[楼主] 2007-06-15 21:27 | Dflying Chen      
@Anthan
第二卷中有例子:8.2.2 完善的客户端DataTable对象

  回复  引用  查看    
#16楼 2007-06-18 17:18 | Clingingboy      
赶快出书吧,期待ing
  回复  引用  查看    
#17楼[楼主] 2007-06-19 16:32 | Dflying Chen      
@Clingingboy
很快啦,谢谢支持!

  回复  引用  查看    
#18楼 2007-06-21 17:19 | MK2      
链接过去, 看到了"8.2.3 客户端DataSource数据源", 就是说可以Binding了...
  回复  引用  查看    
#19楼[楼主] 2007-06-22 10:38 | Dflying Chen      
@MK2
恩,可以

  回复  引用  查看    
#20楼 2007-07-13 09:52 | winnerzone      
如果大家用的是五月的ctp那么要修改下下面这句话:
<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>

将版本号Version=1.0.61025.0改成Version=1.1.61025.0
要不会报错.

  回复  引用  查看    
#21楼[楼主] 2007-07-13 10:00 | Dflying Chen      
@winnerzone
那个Version不写也可以,呵呵

  回复  引用  查看    
#22楼 2007-07-31 22:27 | Leepy      
@winnerzone说得对啊,不写不可以啊,我试过了
  回复  引用  查看    
#23楼[楼主] 2007-08-02 11:57 | Dflying Chen      
@Leepy
为什么呢?

  回复  引用  查看    
#24楼 2007-08-22 10:35 | 小J[未注册用户]
版本号是不是可以不写呀,如果版本号写错,会出现找不到 webservice对象的错误
  回复  引用    
#25楼[楼主] 2007-08-23 19:08 | Dflying Chen      
@小J
一定要写的,不写会找不到

  回复  引用  查看    
#26楼 2007-11-13 10:49 | lichanghua[未注册用户]
关于DataTable和DataSet自动转换问题:我下载的是ASP.NET Futures (July 2007)版本,按书中3.7.6节做实例不行,后我知道是版本问题,将版本号Version=1.0.61025.0改成Version=1.2.61025.0行不通,问在ASP.NET Futures (July 2007)版本下如何进行DataTable和DataSet自动转换?

  回复  引用    
#27楼 2007-11-13 10:53 | lichanghua[未注册用户]
顺问一下1.在VS工具箱中ASP.NET Futures-Dynamic Data的DynamicList等控件如何使用?
2.如何使用新建的Dynamic Data Web Form项的网页:TableName.aspx

  回复  引用    
#28楼 2007-12-28 18:56 | Julio[未注册用户]
关于获取DataTable的时候,遇到一个问题,提示“DataService”未定义!
同时,其他使用WebService的页面也提示对应的WebService未定义!
如果不添加<jsonSerialization>配置节,就没有这样的错误,当然也获取不到需要的DataTable!

  回复  引用    
#29楼 2008-01-06 13:40 | i.Posei      
我也遇到了Julio这样的问题。
  回复  引用  查看    
#30楼 2008-02-20 23:07 | abc_abc[未注册用户]
ajax调用返回DataSet调试时可以看到数据,但是在javascript中取值的时候老是undefined,怎么回事情呀?
function onSucceeded(response)//断点处可以看到response的数据,是个DATASET数据也可以看到。WEBSERVICE测试的时候也有XML格式的dataset返回,搞不清楚了
{
if (response.value != null)//这里是为空,如果注释掉这里,下面执行到var ds = response.value;的时候ds ¦undefined
{
debugger; //这里也是undefined
    var ds = response.value;
if(ds != null && typeof(ds) == "object" && ds != null)
{
for(var i=0; i <ds.Tables[0].Rows.length; i++)
     {
     var name=ds.Tables[0].Rows[i].AREA;
       var id=ds.Tables[0].Rows[i].AIRWAY;
       document.getElementById("ctl00_ContentPlaceHolder1_DDLSAIRWAY").options.add(new Option(name,id));
     }

}
return

}

  回复  引用    
#31楼 2008-04-09 03:05 | Suffer[未注册用户]
for(var rowIndex=0;rowIndex<rows.length;++rowIndex)
{
var bulider=new Sys.StringBuilder();
bulider.append("<li>rows[rowIndex][VideoName]</li>");
$get("result").innerHTML=bulider.toString();
}
已经获取到DataSet,也在输出窗口看到了数据,但运行下来就报"'length' is null or not an object"这样的错误...

  回复  引用    
#32楼 2008-05-23 17:16 | pancult[未注册用户]
我用的是VS2008 ,AJAX 异步传递能 不安装TCP吗?请指教,最好能给我回封邮件,谢谢。
  回复  引用    
#33楼 2008-07-10 16:47 | 小邱同志[未注册用户]
如果用的是vs2008应该怎么安装ctp呢
请指教

  回复  引用    



发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 784053




相关文章:

相关链接: