深入Atlas系列:Web Sevices Access in Atlas示例(5) - 自定义TypeConverter把基础类型转换为复杂类型...

  在上一个示例《深入Atlas系列:Web Sevices Access in Atlas示例(4) - 使用HTTP GET调用Web Services方法》中我们了解到如何通过HTTP GET来访问Web Services方法。很显然,使用HTTP GET依靠Query String传递参数,于是在客户端拿到的总是基本数据类型String。幸好,在Atlas中,对于基础类型的参数,如果遇到了一个字符串,则会设法将其转换成一个合适的类型。因此,在使用HTTP GET方法传递参数时,在Web Services方法里能够使用个中各样的基础类型。

但是,这显然远远不够,Atlas也不会将这个问题置之不理。在Atlas中,自提供了一套自定义机制可以将基础类型转换为复杂类型。在《深入Atlas系列:Web Sevices Access in Atlas示例(2) - 自定义JavaScriptConverter处理循环引用对象》里我们知道了依靠自定义JavaScriptObject类可以为一个或一系列的类提供自定的序列化和反序列化的功能。在现在这片文章中,我将使用示例演示一下如何使用TypeConverter自定义基础类型到复杂类型的转换(请注意,这个方法是提供了基础类型向复杂类型转换的功能,在使用HTTP POST传递Web Services参数时也能使用)。在某些最简单的需求下,就可以使用这个方法,它比自定义一个JavaScriptObject相对要方便一些。

TypeConverter对于编写ASP.NET Server Control的朋友可谓是再熟悉不过了。我们通过示例,一步一步地来查看如何在Atlas中使用自定义TypeConverter。

首先,定义一个复杂类型Employee:
29174338_Bn1e.gif 29174338_oodc.gif Employee类
1 [TypeConverter(typeof(EmployeeConverter))]
2 public class Employee
3 {
4     public string Name;
5 
6     public int Age;
7 }

可以看到,我们使用了TypeConverterAttribute将稍后会讲解的EmployeeConverter关联到Employee上。

接着,和上一个例子一样,我们写一个支持HTTP GET访问的Web Services方法,只是参数使用了复杂类型。
29174338_Bn1e.gif 29174338_oodc.gif HttpGetEmployeeService
 1 [WebService(Namespace = "http://tempuri.org/")]
 2 [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
 3 public class HttpGetEmployeeService  : System.Web.Services.WebService {
 4 
 5     [WebMethod]
 6     [WebOperation(true, ResponseFormatMode.Xml)]
 7     public XmlDocument SubmitEmployee(Employee employee)
 8     {
 9         XmlDocument responseDoc = new XmlDocument();
10         responseDoc.LoadXml(
11             "<?xml-stylesheet type=\"text/xsl\" href=\"Employee.xsl\"?>" +
12             "<Employee><Name></Name><Age></Age></Employee>");
13         responseDoc.SelectSingleNode("//Name").InnerText = employee.Name;
14         responseDoc.SelectSingleNode("//Age").InnerText = employee.Age.ToString();
15         return responseDoc;
16     }    
17 }

然后是所需的Xslt文件:
29174338_Bn1e.gif 29174338_oodc.gif Employee.xsl
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <xsl:stylesheet version="1.0"
 3     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 4     <xsl:template match="/Employee">
 5         <html>
 6             <head>
 7                 <title>Thanks for your participation</title>
 8             </head>
 9             <body style="font-family:Verdana; font-size:13px;">
10                 <h4>Here's the employee you submitted:</h4>
11                 <div>
12                     <xsl:text>Name: </xsl:text>
13                     <xsl:value-of select="Name" />
14                 </div>
15                 <div>
16                     <xsl:text>Age: </xsl:text>
17                     <xsl:value-of select="Age" />
18                 </div>
19             </body>
20         </html>
21     </xsl:template>
22 </xsl:stylesheet> 

上面这些对于看过之前一片文章的朋友们来说应该很熟悉。接下来,我们就进入正题,定义一个EmployeeConverter。代码如下:
29174338_Bn1e.gif 29174338_oodc.gif EmployeeConverter类
 1 public class EmployeeConverter : TypeConverter
 2 {
 3     public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
 4     {
 5         if (sourceType == typeof(String))
 6         {
 7             return true;
 8         }
 9 
10         return false;
11     }
12 
13     public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
14     {
15         IDictionary<stringobject> dictObj = 
16             JavaScriptObjectDeserializer.DeserializeDictionary(value.ToString());
17 
18         Employee emp = new Employee();
19         emp.Name = dictObj["Name"].ToString();
20         emp.Age = (int)dictObj["Age"];
21 
22         return emp;
23     }
24 }

EmployeeConverter继承了TypeConverter,首先覆盖CanConvertFrom方法表明使用EmployeeConverter可以将一个String转换成另一个对象。接着在覆盖ConvertFrom方法,将传入的value值转换为一个复杂对象Employee。这里为了方便,我们把Employee对象在客户端JOSN序列化,然后在服务器端再序列化回来,事实上,这种基础类型到复杂类型的转换,完全可以使用任何方式。

代码都非常简单,也容易理解,因此我们直接看一下使用代码。由于代码很少,就将Javascript和HTML一并贴出了:
29174338_Bn1e.gif 29174338_oodc.gif Javascript和HTML代码
 1 <html xmlns="http://www.w3.org/1999/xhtml" >
 2 <head>
 3     <title>Convert Primitive Object using Customized TypeConverter</title>
 4     <script language="javascript">
 5         function submitEmployee()
 6         {
 7             var emp = new Object();
 8             emp.Name = $("txtName").value;
 9             emp.Age = parseInt($("txtAge").value, 10);
10             
11             var serializedEmp = Sys.Serialization.JSON.serialize(emp);
12             var url = "HttpGetEmployeeService.asmx?mn=SubmitEmployee&employee=" + encodeURI(serializedEmp);
13             window.open(url);
14         }
15     </script>
16 </head>
17 <body style="font-family:Verdana; font-size:13px;">
18     <form runat="server">
19         <atlas:ScriptManager ID="ScriptManager1" runat="server" />
20     
21         <div>Name:<input type="text" id="txtName" /></div>
22         <div>Age:<input type="text" id="txtAge" /></div>
23         <input type="button" value="Submit" onclick="submitEmployee();" />
24     </form>
25 </body>
26 </html>

在奠基“Submit”按钮之后,会调用submitEmployee函数,这个函数根据用户的输入构造一个Employee对象,然后再使用和上一篇文章相同的办法拼接URL,最后使用window.open打开。

我们来看一下使用效果,首先是刚打开窗口:
29174338_zyGa.jpg

输入内容并点击Submit,注意新窗口中的地址栏信息:
29174339_tmYk.jpg

这个示例就到此为止了,这个就是自定义TypeConverter的使用。

事实上,正如前面我提到的,完全可以不使用JSON方式来传递对象。个人认为,TypeConverter最大的作用是可以隐藏一个复杂类型的细节,例如我们将用户认证信息加密后传输到客户端,然后客户端使用字符串形式传递给一个Web Services方法,然后使用自定义TypeConverter获得解密后的对象,这样就可以安全地传递信息。

不过,有了JavaScriptObject和TypeConverter,我们该如何选择呢?根据我的理解,在选择时,我们可以这样判断:

1、如果需要隐藏复杂类型细节,则使用TypeConverter。
2、如果需要在客户端提供代理,则使用JavaScriptObject。
3、如果需要扩展已有的类,使用JavaScriptObject。
4、如果无法确定用哪种扩展机制,使用自定义JavaScriptObject。



点击这里下载示例源代码。

转载于:https://my.oschina.net/abcijkxyz/blog/721054

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值