最近开始着手学习ASP.NET AJAX,在园里看了很多关于这方面的文章,自己也曾买了关于ASP.NET AJAX的书籍,本文我将借鉴于老赵的WebCast深入浅出系列课程第五讲以记学习笔记的形式和大家一起学习关于ASP.NET AJAX客户端访问Web Service参数类型的序列化与反序列化内容.
由于涉及到是示例较多,本文我将分为两部分.
本文的内容包括
● 复杂参数类型基本使用方式
● 生成复杂参数类型的客户端代理
● 客户端代理的作用
● 使用JavaScriptConverter
● 自定义JavaScriptConverter
一、复杂参数类型基本使用方式
首先我们定义一个Employee类:
Emploee类
1public class Employee
2{
3 /**//// <summary>
4 /// 作为参数的类型一定要有默认的构造函数
5 /// </summary>
6 public Employee()
7 {
8 }
9
10 public Employee(string name, string sex, string age)
11 {
12 this.Name = name;
13 this.Sex = sex;
14 this.Age = age;
15 }
16
17 private string _name;
18 public string Name
19 {
20 get { return _name; }
21 set { _name = value; }
22 }
23
24 private string _sex;
25 public string Sex
26 {
27 get { return _sex; }
28 set { _sex = value; }
29 }
30
31 private string _age;
32 public string Age
33 {
34 get { return _age; }
35 set { _age = value; }
36 }
37}
接下来我们定义一个WebService的方法,提供给客户端调用,返回复杂类型(Employee) ;
1/**//// <summary>
2/// EmployeeWebService 的摘要说明
3/// </summary>
4[WebService(Namespace = "http://tempuri.org/")]
5[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
6[ScriptService]
7public class EmployeeWebService : System.Web.Services.WebService {
8
9 public EmployeeWebService () {
10
11 //如果使用设计的组件,请取消注释以下行
12 //InitializeComponent();
13 }
14
15 [WebMethod]
16 public Employee GetEmployeeOne()
17 {
18 return new Employee("beniao", "boy", "22");
19 }
20
21 [WebMethod]
22 public Employee GetEmployeeTwo(Employee employee)
23 {
24 return new Employee(employee.Name, employee.Sex, employee.Age);
25 }
26}
这其实是很简单的,我就不做过多的说明。我门先为ScriptManager指向我门上面开发的Web Service。并放置两个按扭来实现调用,最后我们将返回的结果显示在一个DIV上。
1<asp:ScriptManager ID="ScriptManager1" runat="server" >
2 <Services>
3 <asp:ServiceReference Path="EmployeeWebService.asmx" />
4 </Services>
5 </asp:ScriptManager>
6
7 <input id="Button1" type="button" value="无参数交互" onclick="GetEmployeeOne();" />
8 <input id="Button2" type="button" value="带参数交互" onclick="GetEmployeeTwo();" />
9 <br /><br />
10 <div id="Result" style="width:230px;height:30px;font-weight:bold;font-size:medium;background-color:#CCC;"></div>
客户端的调用是怎么定义的呢?分别有发送请求的函数和回调函数:
1<script type="text/javascript">
2 function GetEmployeeOne()
3 {
4 EmployeeWebService.GetEmployeeOne(CallBack);
5 }
6 function GetEmployeeTwo()
7 {
8 //使用JSON进行传输
9 var employee = {"Name":"Yuang", "Sex":"girl", "Age":"21"};
10 EmployeeWebService.GetEmployeeTwo(employee , CallBack);
11 }
12
13 //回调函数
14 function CallBack(employee)
15 {
16 var obj=document.getElementById("Result");
17 obj.innerHTML=String.format("Name:{0} Sex:{1} Age:{2}",
18 employee.Name,
19 employee.Sex,
20 employee.Age);
21 } 如上面所介绍,演示了一个关于复杂参数的基本使用,运行结果如下所示:
二、生成复杂参数类型的客户端代理
这一步其实是很简单的.代码我们就重用上面的代码就可以了.新建立一个页面,把上面示例的页面代码Copy过来作适当的修改就OK了.我门先看看客户端的代码定义:
1<asp:ScriptManager ID="ScriptManager1" runat="server">
2 <Services>
3 <asp:ServiceReference Path="EmployeeWebService.asmx" InlineScript="true" />
4 </Services>
5 </asp:ScriptManager>
6
7 <input id="Button2" type="button" value="使用客户端代理" onclick="GetEmployee();" />
8 <br /><br />
9 <div id="Result" style="width:230px;height:30px;font-weight:bold;font-size:medium;background-color:#CCC;"></div>
同上一个例子一样,我们将ScriptManager指向EmployeeWebService.asmx这个Web服务,下面是JS定义,服务器端的发方法为了在客户端调用方法,在客户端会生成方法的代理,那怎么使用客户端方法的代理呢?下面我们来看看通过客户端代理的使用,代码如下定义:
<script type="text/javascript">
function GetEmployee()
{
//使用客户端代理替换JSON字符串
var employee = new Employee();
employee.Name="beniao";
employee.Sex="boy";
employee.Age="22";
EmployeeWebService.GetEmployeeTwo(employee , CallBack);
}
function CallBack(employee)
{
var obj=document.getElementById("Result");
obj.innerHTML=String.format("Name:{0} Sex:{1} Age:{2}",
employee.Name,
employee.Sex,
employee.Age);
}
</script>
我们很清楚的看到上面示例中我们使用的是一个Employee对象,而非上个示例中的JSON字符串了,其实使用客户端代理和JSON字符串是完全等价的. 下面是两者的定义:
1//使用JSON进行传输
2var employee = {"Name":"beniao", "Sex":"boy", "Age":"22"};
3----------------------------------------------------------------------
4//使用客户端代理替换JSON字符串
5var employee = new Employee();
6employee.Name="beniao";
7employee.Sex="boy";
8employee.Age="22";
9
那Employee这个客户端代理是怎么生成的呢?这并非是我们在服务端定义的Employee类,不过与它还是有很大的关系,那这个客户端代理是怎么生成的以及通过什么样的方法可以查看到这个代理的生成呢?前面我们在为ScriptManager引入Web服务的时候后面加入了这样一个属性:InlineScript="true",通过设置它我们就能够在客户端显示生成的客户端代理.那怎么查看呢?运行你所开发的页面,右键查看源文件,里面有下面的定义(不同的代理会有所不同,下面是本例中生成的代理):
1EmployeeWebService.prototype={
2GetEmployeeOne:function(succeededCallback, failedCallback, userContext) {
3return this._invoke(EmployeeWebService.get_path(), 'GetEmployeeOne',false,{},succeededCallback,failedCallback,userContext); },
4GetEmployeeTwo:function(employee,succeededCallback, failedCallback, userContext) {
5return this._invoke(EmployeeWebService.get_path(), 'GetEmployeeTwo',false,{employee:employee},succeededCallback,failedCallback,userContext); }}
6EmployeeWebService.registerClass('EmployeeWebService',Sys.Net.WebServiceProxy);
7EmployeeWebService._staticInstance = new EmployeeWebService();
8EmployeeWebService.set_path = function(value) { EmployeeWebService._staticInstance._path = value; }
9EmployeeWebService.get_path = function() { return EmployeeWebService._staticInstance._path; }
10EmployeeWebService.set_timeout = function(value) { EmployeeWebService._staticInstance._timeout = value; }
11EmployeeWebService.get_timeout = function() { return EmployeeWebService._staticInstance._timeout; }
12EmployeeWebService.set_defaultUserContext = function(value) { EmployeeWebService._staticInstance._userContext = value; }
13EmployeeWebService.get_defaultUserContext = function() { return EmployeeWebService._staticInstance._userContext; }
14EmployeeWebService.set_defaultSucceededCallback = function(value) { EmployeeWebService._staticInstance._succeeded = value; }
15EmployeeWebService.get_defaultSucceededCallback = function() { return EmployeeWebService._staticInstance._succeeded; }
16EmployeeWebService.set_defaultFailedCallback = function(value) { EmployeeWebService._staticInstance._failed = value; }
17EmployeeWebService.get_defaultFailedCallback = function() { return EmployeeWebService._staticInstance._failed; }
18EmployeeWebService.set_path("/Web/EmployeeWebService.asmx");
19EmployeeWebService.GetEmployeeOne= function(onSuccess,onFailed,userContext) {EmployeeWebService._staticInstance.GetEmployeeOne(onSuccess,onFailed,userContext); }
20EmployeeWebService.GetEmployeeTwo= function(employee,onSuccess,onFailed,userContext) {EmployeeWebService._staticInstance.GetEmployeeTwo(employee,onSuccess,onFailed,userContext); }
21var gtc = Sys.Net.WebServiceProxy._generateTypedConstructor;
22if (typeof(Employee) === 'undefined') {
23var Employee=gtc("Employee");
24Employee.registerClass('Employee');
25}
通过上面的客户端代理我们可以查看到,在客户端为我们注册了一个gtc("Employee"),生成这样的代理之后,我们就可以在客户端通过代理的方法来使用Employee类了.这或许可以说是一种映射吧(个人意见).要让服务器在运行的时候生成客户端的代理其实很简单,上面说这么多归根到底就一个代码实现,我们只需要在服务端方法上加入[GenerateScriptType(typeof(Employee))]这样一句话就可以了,完整定义如下:
1[WebMethod]
2[GenerateScriptType(typeof(Employee))] //在客户端生成一个复杂的代理
3public Employee GetEmployeeTwo(Employee employee)
4{
5 return new Employee(employee.Name, employee.Sex, employee.Age);
6}
三、客户端代理的作用
事实上我们在使用客户端代理的时候,有很多对象对我们开发都是很有用的,其实在使用客户端代理的实质就是为对象在客户端生成了一个"__type"标记,如我们上面使用Employee类,在客户端生成的"__type"标记为:
__type="Employee";
下面我们来看看一个实例,由于上面我们定义了Employee,这里我们就定义一个User做为实例的对象.
1public abstract class User
2{
3 public abstract string GetSalary();
4}
5
6/// <summary>
7/// 全职
8/// </summary>
9public class FullTime : User
10{
11 public override string GetSalary()
12 {
13 return "全职:10000.0";
14 }
15}
16
17/// <summary>
18/// 兼职
19/// </summary>
20public class PartTime : User
21{
22 public override string GetSalary()
23 {
24 return "兼职:2000.0";
25 }
26}
我们上面定义了User类,并抽象了一个方法getSalary(),在服务器端这里是可以实现多态的,接下来我们为该对象(User)对象开发一个Web Service;
1[WebService(Namespace = "http://tempuri.org/")]
2[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
3[ScriptService]
4public class UserWebService : System.Web.Services.WebService {
5
6 public UserWebService () {
7
8 //如果使用设计的组件,请取消注释以下行
9 //InitializeComponent();
10 }
11
12
13 [WebMethod]
14 [GenerateScriptType(typeof(FullTime))]
15 [GenerateScriptType(typeof(PartTime))]
16 public string GetUserSalary(User user)
17 {
18 return user.GetSalary();
19 }
20}
在客户端我们通过传递不同的字类对象在WebService里通过多态的方式去调用具体的实现类.我们现在来看看在客户端怎么通过__type标记来实现这种"多态"的调用.
1<script type="text/javascript">
2 function getSalary()
3 {
4 var user = new Object();
5 user.__type = $get("UserType").value;
6 UserWebService.GetUserSalary(user,onSucceeded);
7 }
8
9 function onSucceeded(result)
10 {
11 $get("Result").innerHTML = result;
12 }
13 </script>
我们在客户端通过指定不同的对象(也就是为__type标记指定不同的客户端类型),服务器端根据标记选择反序列化的目标类型来实现"多态"效果的调用;
1<asp:ScriptManager ID="ScriptManager1" runat="server">
2 <Services>
3 <asp:ServiceReference Path="UserWebService.asmx" />
4 </Services>
5 </asp:ScriptManager>
6 <select id="UserType">
7 <option value="FullTime">全职</option>
8 <option value="PartTime">兼职</option>
9 </select>
10
11 <input id="btnSalary" type="button" value="计算工资" onclick="getSalary();" /><br />
12 <div id="Result" style="width:230px;height:30px;font-weight:bold;background-color:#CCC;"></div>
通过下拉选择控件中选择不同的类型(FullTime,PartTime),动态的指定__type标记的值.将调用结果呈现在DIV里显示出来,运行结果如下所示;
关于客户端访问Web Service--参数类型的序列化与反序列化的前部分就先介绍到这里,后续部分我将尽快记录下来,我很喜欢以写文章的这种方式来做笔记,喜欢大家多多支持与指点.文章里的不妥之处还望前辈们多多指正,谢谢.
文章里使用的示例代码我将在后半部分完成后提供给大家参考.
分享到:
相关推荐
在标题中提到的"(转)客户端访问Web Service--参数类型的序列化与反序列化(二)",这可能是指在系列文章的第二部分,作者深入讨论了在客户端调用Web Service时,如何处理各种参数类型的序列化和反序列化问题。...
- 创建一个SoapSerializationEnvelope实例,将SoapObject放入其中,以确保SOAP消息的序列化和反序列化。 - 创建一个HttpTransportSE实例,通过它将SOAP请求消息发送到服务器,并接收响应。 - 使用上述实例调用Web ...
在这个"Web service 序列化实验教程"中,我们将专注于如何使用XML进行序列化,这是Web服务中一个至关重要的环节。XML(eXtensible Markup Language)是一种标记语言,常用于数据交换,因为它具有良好的可读性和平台...
- **序列化和反序列化**:`System.Text.Json`或第三方库如Newtonsoft.Json用于JSON数据的序列化和反序列化,便于在客户端和服务端之间传递对象。 5. **项目结构**: - `Restful-Service-And-Restful-Client-...
3. **数据序列化与反序列化**:客户端可能需要将数据转换为JSON或XML格式,以便于在网络间传输。C#提供了`JsonSerializer`(System.Text.Json)或`DataContractSerializer`(用于.NET Framework的WCF服务)等工具...
在WCF服务中,当服务方法需要返回一个对象或者接受一个对象作为参数时,就需要进行序列化。序列化是将对象转换为字节流的过程,以便可以通过网络进行传输。反序列化则是相反的过程,将接收到的字节流恢复为原来的...
2. **实现自定义序列化**: 定义自定义类型`CustomSerializedObject`,并使用`IXmlSerializable`接口来实现自定义序列化和反序列化。这个接口有两个方法需要实现:`ReadXml` 和 `WriteXml`。 ```csharp public class...
描述中提到的“支持类的传输”意味着在Java调用.NET Web Service时,不仅传递基本类型的数据,还能传递复杂的对象,这通常需要序列化和反序列化的支持。在.NET中,我们可以使用DataContract和DataMember特性标记类...
- **数据类型转换**:确保数组元素的数据类型与Web Service期望的数据类型相匹配。 - **序列化**:数组需要按照SOAP规范进行序列化。 - **解析响应**:处理返回的SOAP响应时,注意正确地反序列化数组数据。 #### 七...
- **XML 数据类型到 Java 类型的映射**:实现数据序列化。 - **可扩展类型映射**:支持自定义数据类型的映射。 - **SOAP Message Handler 框架**:处理 SOAP 消息的框架。 - **打包**:将 Web Service 打包成...
本标准定义了一个Web Coverage Processing Service(WCPS)的规范,它允许客户端通过HTTP协议提交覆盖数据处理请求,并接收处理后的结果。WCPS的目标是提供一种灵活且强大的机制来访问、处理和分发多维覆盖数据,如...
在Web Service的上下文中,Compact DataSet可以作为在服务器和客户端之间传递数据的有效方式,因为它占用的内存更少,而且在序列化和反序列化过程中效率较高。 Web Service通常用于跨平台、跨系统的数据交换,但...
在这个"WebService Axis1.4接口服务序列/反序列复杂项目实例"中,我们将深入探讨如何在 Axis1.4 中处理复杂的参数、自定义实体对象的序列化与反序列化,以及客户端的复杂调用。 首先,让我们理解序列化和反序列化的...
这在JSON Web Service中至关重要,因为服务需要接收和发送JSON格式的数据,以实现与客户端的有效通信。 在使用这些库构建JSON Web Service时,开发人员首先需要导入这些jar文件到他们的项目中。然后,他们可以利用...
在Linux环境下利用gSOAP开发Web Service服务端与客户端程序,是一项深入理解Web Service技术与Linux平台编程的关键技能。本文将详细解析如何在Linux系统中利用gSOAP工具包创建Web Service服务端与客户端程序,包括...
5. **客户端消费服务**:创建一个WCF客户端,调用服务的方法,此时就会涉及数据的序列化和反序列化。 ```csharp var client = new MyServiceClient(); Person person = new Person() { Name = "John", Age = 30 }; ...
代理类负责序列化参数,发送SOAP消息,接收响应,并反序列化结果。 #### 总结 通过以上步骤,我们不仅了解了如何创建和部署Web Service,还学会了如何从客户端调用Web Service。Web Service提供了一种强大且灵活的...
3. **数据类型映射**:gSOAP支持多种数据类型的自动转换,包括基本数据类型、结构体、枚举等,使得C/C++代码可以直接操作这些类型,而无需关心底层的XML序列化和反序列化过程。 4. **HTTP和HTTPS支持**:gSOAP不仅...
- **XML序列化**:如果Web Service返回的数据格式为XML,ASP.NET AJAX可以方便地处理XML序列化和反序列化。 综上所述,ASP.NET AJAX为Web Service和页面类方法提供了强大的异步调用支持,大大简化了客户端与服务器...