.NEt专家博客!

【T2噬菌体】ASP.NET AJAX客户端编程之旅(三)—数据转换&序列化

上一篇 / 下一篇  2008-07-24 11:36:08 / 个人分类:.net

摘要

      通过前两篇文章,我们知道使用了ASP.NET AJAX框架后,在JavaScript中调用后台WebService方法非常方便,几乎可以看做是“直接调用”。那么,这里引出了一个问题:调用方法就牵扯到参数的传递,而JavaScript和C#毕竟是两种不同的语言,数据类型怎么沟通?简单型数据类型还好说,如果我们需要的参数是个复杂类型呢?如分层架构中经常用到实体类做参数,我们在后台定义实体类类型,但是JavaScript可不知道这种定义,也没有相应数据类型,那么要如何解决这个问题呢?再进一步,如果需要的参数是个泛型集合呢?在JavaScript中又要如何表示这种类型?这一篇将解决这些问题。

先来看ASP.NET AJAX给你变个魔术

      我们都知道,使用分层架构开发系统时,使用实体类作为参数很很普遍的。那么如果我们需要调用的某个后台方法中需要实体类做参数,应该如何进行呢?毕竟C#中定义的实体类在JavaScript中可不认识啊。先不要着急,跟我做以下几步,我们一起来看个魔术。

      1.新建一个ASP.NET AJAX Enabled Web Site工程,并添加系统文件夹App_Code。

      2.我们在App_Code里新建一个C#类文件StudentInfo.cs,其内容如下:

StudentInfo.cs:

 1using System;
4D+ZB ~.a(i/Sz\,fM0
 2ITPUB个人空间4@^c&o*d`n(mc G
 3[Serializable]
,KwQ],C+x eH0
 4public class StudentInfoITPUB个人空间P \+C HhH#sbt\k
 5{ITPUB个人空间 lW%v3u c$a V
 6    private string _name;
7l*G}~u5F:XJV0
 7    private int _age;
|.nO1ZFd3?h-lr&c0
 8    private string _college;ITPUB个人空间$_$XQS e3F-s`$\
 9ITPUB个人空间5m)ct#WL cWGA*A)a
10    public StudentInfo() { }
N+g't*B0M9O o C(^8^u0
11ITPUB个人空间0M(k m/D ^ mPy@
12    public string Name
Qt oOO0
13    {ITPUB个人空间t9vl0K"R%k
14        get return this._name; }ITPUB个人空间)~h7c*s(w3I2\&|
15        set this._name = value; }ITPUB个人空间 f9k(s [|~(O d)?2||
16    }

c p A5j C3K(i B&C0
17
!S2Jr,h!B Fi[0
18    public int Age
/E;u'T;R;Ujxx"g V0
19    {ITPUB个人空间 O,N&t)e{&Du-}
20        get return this._age; }ITPUB个人空间 hs{o^,\%c
21        set this._age = value; }
)AC&B7you*b.P@0
22    }
ITPUB个人空间(t bqr'~(^
23ITPUB个人空间3j`S+_tF+Vs
24    public string CollegeITPUB个人空间o g1|1H b
25    {ITPUB个人空间^.x'Z6jH,n"~[N5q4g
26        get return this._college; }ITPUB个人空间 t'@)De-tU4M/i#[@
27        set this._college = value; }ITPUB个人空间P8W'bMx I{&T
28    }

Y.w!M,\ C"`Sc1a3]0
29}

      这是一个典型的实体类,相信做过分层架构的朋友一定经常使用到类似的代码。这里要特别注意两点:一是这个类上面有一个[Serializeable]属性,这表明此类可以被序列化,另外就是这个类有一个空的构造函数。

      3.接着,我们在网站根目录下添加一个WebService:StudentService.asmx,其代码如下:

StudentService.cs:

 1using System;
*? ]0D{1pV0
 2using System.Web;
4_%_#FU7RU1D0
 3using System.Collections;
~t$OG,g!Ww0
 4using System.Web.Services;ITPUB个人空间MP3zA:YLC;D6F _
 5using System.Web.Services.Protocols;
1uRA5AU P0
 6using System.Web.Script.Services;
7E;m`z%F0
 7ITPUB个人空间9C;D,a[7D)r8Y)k%i/i
 8[WebService(Namespace = "http://tempuri.org/")]ITPUB个人空间|c-@;[^"S:d9h
 9[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]ITPUB个人空间,p0LD1VC-ht} v4^
10[ScriptService]
L%AC'KBp'v#N0
11[GenerateScriptType(typeof(StudentInfo))]
i*C w#S_S5iW1s0
12public class StudentService : System.Web.Services.WebService
2eBcV VYq0
13{ITPUB个人空间Q5Wm(xF*\)?M
14    public StudentService() { }ITPUB个人空间 ji|Z R1A H
15
w1@ s(A z+D-U0
16    [WebMethod]
EUR-@i9[0
17    public string ShowStudentInfo(StudentInfo student)ITPUB个人空间j3N;o({0U3F
18    {
9T&j5}5o1o)q%Yt0
19        return "学生姓名:" + student.Name + "<br />年龄:" + student.Age + "<br />所在院系:" + student.College;ITPUB个人空间^:?!w?sQ8[X
20    }
ITPUB个人空间{Tl-a#C
21}

      ShowStudentInfo这个方法接收一个StudentInfo类型的参数,并根据这个实体类的信息组合成一段字符串返回。

      4.接着,在网站根目录下新建一个ajax.js文件,内容如下:

ajax.js:

 1function btnShowStudentInfo_onClick()
-}Q1SD8d5k v0
 2{
"M6E5Y8`@%L0
 3    var student=new StudentInfo();ITPUB个人空间!rO1ac6mRP*jf
 4    student.Name="张无忌";ITPUB个人空间_5M2{&{"_ k
 5    student.Age="20";
[$J u c-Rc0
 6    student.College="计算机学院";ITPUB个人空间K!N"Sr*B[!o7I
 7    
!wc^Gd RX0
 8    StudentService.ShowStudentInfo(student,CallBackFunction);
czi-M#p osP0
 9}

t_T ]h$E `6Je0
10
&B*@y3wK-@ fE#}0
11function CallBackFunction(responseText)ITPUB个人空间z:f%X }/eWU*_
12{ITPUB个人空间(Oq"E*@r
13    $get("result").innerHTML=responseText;
E8y@Yw.q!ZR0
14}

      这里我们大胆的直接初始化了一个StudentInfo,为什么说大胆呢?不要忘了,我们的StudentInfo类型可是在C#中定义的,JavaScript里可压根没有这个类型,当时我们这里却好像在写C#似的,不但初始化了这个类,还给其中成员赋值,并且当作参数传给了后台方法。这样能成功吗?我们接着看看吧。

      5.Default.aspx作为主页,我们添加如下内容:

Default.aspx:

 1<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
G9Wf9cJ0
 2ITPUB个人空间Q*[n0WL7Z*F5] _
 3<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">ITPUB个人空间'iP8G9}x [/B6l
 4<html xmlns="http://www.w3.org/1999/xhtml">ITPUB个人空间'{ug5[xS(qN^
 5<head runat="server">ITPUB个人空间|$m2QA8j2g6W1z!^
 6    <title>复杂类型自动转换测试</title>
"I1a#m+e p X8GY0
 7</head>
N9wk*KPe0
 8<body>ITPUB个人空间8C'},O~h#@ Fn
 9    <form id="form1" runat="server">ITPUB个人空间r5L0wD5K1S4zH
10        <asp:ScriptManager ID="ScriptManager1" runat="server">ITPUB个人空间,r/|gP4WIvi-{L9E
11            <Scripts>ITPUB个人空间]| tw F]f!n9|?
12                <asp:ScriptReference Path="~/ajax.js" />
/l'e6T:o7g7AQ ^ B5L(D0
13            
</Scripts>
8z@aZ|D0
14            <Services>ITPUB个人空间`7o*]PQZ
15                <asp:ServiceReference Path="~/StudentService.asmx" />ITPUB个人空间^2\ fu0G-ki
16            </Services>ITPUB个人空间/HvL/Vi Mv(nx
17        </asp:ScriptManager>ITPUB个人空间s{&} lgG g
18        <div>
y!B'vyq,l0
19            <input id="btnShowStudentInfo" type="button" value="ShowStudentInfo" onclick="btnShowStudentInfo_onClick()" />
+P6Nax}:e8_/o9N0
20            <div id="result"></div>ITPUB个人空间;tO2G k5FE3X.c2x
21        </div>ITPUB个人空间e Aw\{ u)Mg
22    </form>ITPUB个人空间)cqB2vz$[`/gME
23</body>
DY3~O-Z$l{#q0
24</html>

      这里就不用做过多解释了,看过前两篇的朋友肯定很容易就明白这段代码是什么意思。运行后,我们单击按钮,得到如下效果:

 

      可以看到,不仅程序运行没有报错,而且我们在JavaScript中定义的实体类被传到后台,并神奇的变成了C#实体类,作为参数完成了数据传递工作。运行结果非常令人满意。

魔术揭秘

      在上面的例子中,我们没有在JavaScript定义StudentInfo,更没有写代码把JavaScript实体类转换成C#实体类,但是程序正确执行了。很显然,有人替我们做了这一切,那是谁呢?当然是我们亲爱的ASP.NET AJAX。这就是这个框架另一项神奇的功能:前后台间数据类型自动转换,这个转换可不仅包括简单类型,还包括像实体类这样的复杂类型。那么,其工作原理是什么呢?

      仔细看StudentService.cs的代码,在类定义的上面,有一个[GenerateScriptTyep(typeof(StudentInfo))] 属性,秘诀就在这里。当我们给WebService类加上这条属性时,ASP.NET AJAX会在运行时自动为我们生成一个JavaScript版本的StudentInfo类,这个类的所有属性都和C#版的一模一样。所以,我们在JavaScript中实例化并赋值的其实是一个JavaScript版的StudentInfo。而后,当我们调用ShowStudentInfo方法时,ASP.NET AJAX框架会自动将JavaScript版的StudentInfo序列化成JOSN字符串,然后传到后台,后台再将这段字符串反序列化成C#版的StudentInfo,并作为参数传递给ShowStudentInfo,从而顺利完成工作。

      当然,如果某个后台方法返回一个StudentInfo类型的返回值,它也可以准确无误从C#传到JavaScript中。也就是说,序列化和反序列化都是双向的。

自动转换的条件

      知道了上述原理,那么如何才能自动转换呢?或者说具备什么条件的复杂类型才可以自动转换呢?大约有以下几点:

      1.需要在WebService中使用[GenerateScriptTyep()]属性指明要自动生成的复杂数据类型。

      2.该复杂类型必须有一个无参数的构造函数。

      3.该复杂类型的所有公有属性必须有get和set方法。

      另外值得注意的是,生成的JavaScript版本类只包含原类的公有属性,而私有属性和方法是不会映射过来的。应该说,这个技术对使用分层架构的应用特别有用,因为可以直接在客户端使用服务器端的实体类进行数据传输。

ASP.NET AJAX到底能自动转换哪些数据类型?

      1.基本类型将被转换为基本类型。如整形、浮点型、字符串、布尔型、DateTime等。(全自动转换)

      2.枚举类型将被转换为枚举类型。(全自动转换)

      3.复杂类型将转换为同名复杂类型,但只保留公有属性。(需要使用[GenerateScriptTyep(typeof(TypeName))]属性声明)

      4.数组、泛型集合将转换为数组。(全自动转换)

      5.DataTable将转换为JavaScript版的DataTable,但是需要ASP.NET Futures CTP的支持。

结束语

      这一篇中介绍了ASP.NET AJAX中非常有用的一个特性:数据类型自动转换。通过这个功能,使得前台可以更方便的调用后台程序。尤其是使用实体类传递数据会变得非常方便。在下一篇中,将介绍客户端组件的概念、使用客户端组件思想进行JavaScript开发以及简化的DOM操作。


TAG: 微软

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

日历

« 2008-10-08  
   1234
567891011
12131415161718
19202122232425
262728293031 

数据统计

  • 访问量: 45199
  • 日志数: 1163
  • 影音数: 7
  • 文件数: 1
  • 建立时间: 2008-01-04
  • 更新时间: 2008-10-08

RSS订阅

Open Toolbar