随笔-312  评论-12034  文章-2  trackbacks-256

本文来自《ASP.NET AJAX程序设计 第II卷:客户端Microsoft AJAX Library相关》的第三章《异步调用Web Service和页面中的类方法》,请同时参考本章的其他文章

 

3.7 服务器端和客户端数据类型的自动转换

读到这里,细心的读者可能已经发现了:前面的示例程序中传递给Web Service以及从Web Service返回的数据的类型均为简单的字符串或是整数。可是在实际开发中,只传递字符串或整数类型的数据显然是不够用的。那么ASP.NET AJAX异步通讯层对于服务器端.NET类型和客户端JavaScript类型之间的映射是否提供了一些辅助功能呢?也就是说,在使用ASP.NET AJAX与服务器端进行异步通讯时,我们能不能直接传递诸如DateTime、DataTable乃至更加复杂的自定义类型呢?

答案自然非常令人兴奋——没有任何问题!ASP.NET AJAX异步通讯层提供了强大的服务器端.NET类型和客户端JavaScript类型之间自动转换能力,我们只要略加配置,甚至根本不需要任何配置,即可在异步通讯的过程中传递包括基本类型、枚举类型、复杂类型、集合(包括泛型集合)类型、数组类型等数据。

若是在某些特殊情况下这类自动转换无法满足实际需求,我们需要更为精确地完全控制某个类型的转换规则,那么也不用担心——借助于在ASP.NET AJAX异步通讯层强大的可扩展性,开发者可以容易地实现自己的转换方案,并“插入”到现有ASP.NET AJAX异步通讯层中。关于自定义服务器端和客户端数据类型的转换规则,将在第III卷中详细介绍。

本节就将通过示例程序介绍ASP.NET AJAX异步通讯层所提供的服务器端.NET类型和客户端JavaScript类型之间的自动转换功能。

 

3.7.1 基本类型

在本节中,基本类型是指数字类型(包括整型、浮点型等)、字符串类型、布尔类型、时间日期类型等。对于这些类型,ASP.NET AJAX异步通讯层能够自动进行服务器端.NET类型和客户端JavaScript类型之间的转换,无须我们任何干预。

例如对于下面的Web Service定义,其中定义了一个名为SendSimpleTypes()的方法,分别接受整型、浮点型、字符串类型、布尔类型、时间日期的六个参数。SendSimpleTypes()方法没有什么实际功能,仅仅起到演示的作用:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class SimpleTypes : System.Web.Services.WebService
{
    [WebMethod]
    public void SendSimpleTypes(int intVar, float floatVar, 
        string stringVar, bool boolVar, DateTime datetimeVar)
    {
        // just for testing
    }
}

然后在客户端我们可以分别创建这5种类型,并尝试通过ASP.NET AJAX异步通讯层生成的代理传递到该Web Service中:

var intVar = 123;
var floatVar = 123.456;
var stringVar = "hello, this is Dflying";
var boolVar = true;
var datetimeVar = new Date();
 
SimpleTypes.SendSimpleTypes(
    intVar, floatVar, stringVar, boolVar, datetimeVar
);

在Visual Studio中启动调试功能,在前面定义的Web Service方法SendSimpleTypes()的第一行加上一个断点(如图3-10所示)。

图3-10在Web Service方法的第一行设置断点

当程序运行至SendSimpleTypes()方法时,打开Visual Studio的“Locals”窗口(Ctrl+Alt+V,L)可以看到SendSimpleTypes()方法的5个参数均已被正确地传递到了服务器端。如图3-11所示。

图3-11 在“Locals”窗口中查看局部变量的值

 

3.7.2 枚举类型

对于枚举类型,若是某个Web Service代理中有所使用(或者Web Service方法接受枚举类型,或者Web Service方法返回枚举类型)的话,ASP.NET AJAX异步通讯层也将自动为该枚举类型生成客户端JavaScript版本,并负责客户端与服务器端类型之间的转换,同样无须我们任何干预。

例如对于如下Web Service以及其中定义的GetTomorrowDay()方法,用来接受一个类型为System.DayOfWeek类型的枚举,然后返回同样类型的枚举,表示下一天是星期几:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class EnumService : System.Web.Services.WebService
{
    [WebMethod]
    public DayOfWeek GetTomorrowDay(DayOfWeek today)
    {
        return (DayOfWeek)(((int)today + 1) % 7);
    }
}

若是在页面中引入了上面的这个名为EnumService的Web Service代理:

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

然后在页面中书写如下的客户端脚本:

function pageLoad() {
    debugger;
}

在Visual Studio中启动调试后,程序将在ASP.NET AJAX客户端框架初始化完毕时(即执行该pageLoad()方法)停下来(debugger语句)。

参考:关于pageLoad()方法以及ASP.NET AJAX客户端框架的初始化过程,将在第4章中详细介绍。关于debugger语句以及ASP.NET AJAX应用程序的调试方法和技巧,将在第III卷中详细介绍。

这是随便打开一个“Watch”窗口(Ctrl+Alt+W,然后数字键1、2、3或者4均可),在其中输入“System.DayOfWeek”并回车确认。随后点击“System.DayOfWeek”一行左边的加号图标展开其中内容,即可看到ASP.NET AJAX异步通讯层自动为该服务器端枚举类型生成客户端枚举类型中的各个属性。如图3-12所示,注意其中从“Sunday”到“Saturday”的7个枚举值。

图3-12 ASP.NET AJAX异步通讯层为
服务器端System.DayOfWeek枚举类型生成的客户端枚举类型

这样,页面中就拥有了服务器端System.DayOfWeek枚举类型的客户端版本。此后,我们也可以将这个客户端的System.DayOfWeek枚举值直接传递给Web Service:

EnumService.GetTomorrowDay(System.DayOfWeek.Monday, onSucceeded);

服务器端将收到“Monday”,当然这个“Monday”已经是服务器端.NET类型的枚举了,如图3-13所示。

图3-13 服务器端收到客户端传递过来的System.DayOfWeek枚举值

随后客户端的回调函数将收到客户端System.DayOfWeek枚举类型的星期二值(“Tuesday”),如图3-14所示。

图3-14 客户端回调函数收到服务器返回的System.DayOfWeek枚举值

对于我们自定义的.NET枚举类型,ASP.NET AJAX异步通讯层同样将一视同仁地生成客户端版本。例如如下表示太阳系八大行星的枚举类型:

namespace Dflying.MyEnums
{
    public enum Planets
    {
        Mercury,
        Venus,
        Earth,
        Mars,
        Jupiter,
        Saturn,
        Uranus,
        Neptune
    }
}

若是在Web Service方法中用到了的话,例如如下所示的一个Web Service方法,用来随机返回八大行星中的一个:

[WebMethod]
public Planets GetRandomPlanet()
{
    Random r = new Random();
    return (Planets)((int)r.Next(9));
}

ASP.NET AJAX异步通讯层将为其生成相应的客户端代理。如图3-15所示(同样是在Visual Studio的“Watch”窗口中)。

图3-15 ASP.NET AJAX异步通讯层为服务器端自定义枚举类型生成的客户端枚举类型

总结:想要让ASP.NET AJAX异步通讯层为服务器端枚举类型自动生成相应的客户端枚举类型,并在调用过程中传递并接收该枚举,我们需要:

  1. 为Web Service类或Web Service中需要暴露给客户端的方法添加[ScriptService]属性;
  2. 为Web Service中需要暴露给客户端的方法添加[WebMethod]属性;
  3. Web Service类中的某个方法的某个参数或返回值为该枚举类型;
  4. 在页面中的ScriptManager控件中添加对该Web Service的引用;
  5. 在客户端用如下JavaScript语法使用该枚举类型:
    [NameSpace].[EnumName].[EnumKey]
posted on 2007-06-11 07:54 Dflying Chen 阅读(4268) 评论(31)  编辑 收藏 网摘 所属分类: ASP.NET AJAX (Atlas)

评论:
#1楼 2007-06-11 09:01 | yao[未注册用户]
刚到单位,先来尝尝鲜.早读早读..
  回复  引用    
#2楼 2007-06-11 09:10 | Anthan      
每天早上上班第一件事就是读你的post,真是一天精神气爽啊
有的时候前一天自己想的问题第二天就看到了,真是爽啊。
呵呵,今天没抢到沙发,那就板凳吧。
ps:有个问题,JavaScript和.Net转换的精度和规则是一样的吗?

  回复  引用  查看    
#3楼 2007-06-11 10:00 | Cat Chen      
@Anthan
这个要看是什么数据类型的精度了。如果float Plus(float x, float y) {return x+y;},我怀疑在不同的机器上运行的结果有差异是可能的,因为float本来就是不精确的,允许出现1+1=1.9999999999999这样的情况。

  回复  引用  查看    
#4楼 2007-06-11 10:13 | Anthan      
@Cat Chen
这个我明白的,应该准确说取决于cpu的浮点运算的设计吧?
其他的我也一时说不好,在具体的使用过程中遇到了还望两个高人不吝赐教啊!

  回复  引用  查看    
#5楼[楼主] 2007-06-11 10:33 | Dflying Chen      
@yao
:)

  回复  引用  查看    
#6楼[楼主] 2007-06-11 10:34 | Dflying Chen      
@Anthan
谢谢支持!

  回复  引用  查看    
#7楼[楼主] 2007-06-11 10:35 | Dflying Chen      
@Cat Chen
@Anthan
解释得不错,呵呵,反正不能依赖这些阿

  回复  引用  查看    
#8楼 2007-06-11 11:22 | 若寒      
极期待Dflying老大的书出版。。
不知道大家有没有试过用decimal?我试了一下:
WebService代码:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo 
= WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class WSProductions : System.Web.Services.WebService {

    
public WSProductions () {


    }


   
    [WebMethod]
    [ScriptMethod]
    
public DataType GetProduction()
    
{
       
        
return new DataType(79789709898908098990804m,4564545454545454545454m,"long Decimal");
    }

    
}

public class DataType
{
    
private decimal price;

    
public decimal Price
    
{
        
get return price; }
        
set { price = value; }
    }

    
private decimal other;

    
public decimal Other
    
{
        
get return other; }
        
set { other = value; }
    }

    
private string name;

    
public string Name
    
{
        
get return name; }
        
set { name = value; }
    }

    
public DataType(decimal price, decimal other, string name)
    
{
        
this.price = price;
        
this.other = other;
        
this.name = name;
    }

    
}
客户端调用:
 <asp:ScriptManager ID="ScriptManager1" runat="server">
    
<Services>
        
<asp:ServiceReference Path="~/WebService/WSProductions.asmx" />
    
</Services>
    
</asp:ScriptManager>
    
    
<div id="result">
    
    
</div>
    
<input id="Button1" type="button" onclick="GetProduction();" value="button" />
    
<script type="text/javascript">
        
function GetProduction()
        
{
            WSProductions.GetProduction(onSuccess);
        }

        
function onSuccess(result)
        
{
            $get('result').innerHTML 
=  " Price is : " + result.Price.toString() + " <br />  Other is : " +  result.Other + " <br />" +  result.Name;
        }

    
</script>
显示的结果是:
Price is : 7.97897098989081e+22
Other is : 4.5645454545454545e+21
long Decimal
 
能不能显示成原来的decimal的格式?
极盼指教。。再次感谢Dflying 。

  回复  引用  查看    
#9楼[楼主] 2007-06-11 11:29 | Dflying Chen      
@若寒
toString的时候可以选择格式化字符串,请参考:http://www.cnblogs.com/dflying/archive/2007/02/09/646430.html" target="_new">http://www.cnblogs.com/dflying/archive/2007/02/09/646430.html

  回复  引用  查看    
#10楼 2007-06-11 12:56 | 若寒      
太感谢了!!

  回复  引用  查看    
#11楼 2007-06-11 16:28 | WOW玩家      
老大,你那些javascript怎么记住的,vs2005没提示的!
  回复  引用  查看    
#12楼[楼主] 2007-06-11 19:44 | Dflying Chen      
@若寒
不客气

  回复  引用  查看    
#13楼[楼主] 2007-06-11 19:44 | Dflying Chen      
@WOW玩家
看看源代码:)

  回复  引用  查看    
#14楼 2007-06-11 20:18 | Sky Chan[未注册用户]
可惜,沒怎麼實際操練.Net!主要還是工作用不上。
我在想,在Oracle Http服務的PSP頁面能不能用上這ajax!

  回复  引用    
#15楼[楼主] 2007-06-11 20:21 | Dflying Chen      
@Sky Chan
呵呵,这个就需要好好研究了,不过应该是没问题的

  回复  引用  查看    
#16楼 2007-06-11 22:20 | 黑白[未注册用户]
支持,收藏了
  回复  引用    
#17楼 2007-06-11 23:03 | 鼎喜[未注册用户]
写的真不错。
  回复  引用    
#18楼 2007-06-12 00:04 | Leepy      
不错!从文章中多少已经能够看出第三卷所要出的内容的雏形了:)
  回复  引用  查看    
#19楼[楼主] 2007-06-12 10:37 | Dflying Chen      
@黑白
@鼎喜
谢谢

  回复  引用  查看    
#20楼[楼主] 2007-06-12 10:37 | Dflying Chen      
@Leepy
哦?看出什么了?

  回复  引用  查看    
#21楼 2007-06-19 01:01 | Microsoft[未注册用户]
Dflying 老大问下

在本节中,基本类型是指数字类型(包括整型、浮点型等)、字符串类型、布尔类型、时间日期类型等。

这些基本类型包括强类型吗?
比如DateTime,DateTable都可以在Javascript运行?
可是我在Javascript里不能用象下面的代码阿
var a = new DateTime();
var b = new DataTable();

到底在Javascript中可以使用的基本类型有哪些阿?难道只有那些基本的值类型?。。。。

  回复  引用    
#22楼[楼主] 2007-06-19 16:33 | Dflying Chen      
@Microsoft
很多类型都可以,只要从服务器端生成其客户端的代理就可以了,请参考:http://www.cnblogs.com/dflying/archive/2007/06/05/771471.html" target="_new">http://www.cnblogs.com/dflying/archive/2007/06/05/771471.html

  回复  引用  查看    
#23楼 2007-06-25 21:12 | Microsoft[未注册用户]
那@Dflying Chen
我试了,光用Ajax在客户端不能取得DataTable,或DateTime类型的对象,是不是还必须装Microsoft ASP.NET Futures 阿?

  回复  引用    
#24楼[楼主] 2007-06-26 09:30 | Dflying Chen      
@Microsoft
是啊,一定要Futures才可以,请参考:http://www.cnblogs.com/dflying/archive/2007/06/15/784053.html" target="_new">http://www.cnblogs.com/dflying/archive/2007/06/15/784053.html

  回复  引用  查看    
#25楼 2007-06-28 21:45 | Microsoft[未注册用户]
@Dflying Chen
晕~~原来是这样...
还有个问题,关于Ajax组件的
我建了个Asp.net Ajax Control Project项目来开发自己的空间,但是在开发的控件中不能用Sys.Timer,但是我发现微软自己的ToolKit里他缺可以用,我用提示没找到该类型...这个应该不是没装Futures的问题吧?
还有,在Behavior里也不能用setTimeout,我把我Behavior里的方法放进去也出现错误...头大~~~

  回复  引用    
#26楼[楼主] 2007-07-03 20:48 | Dflying Chen      
@Microsoft
感觉好奇怪啊?能把示例代码贴上来一些么?

  回复  引用  查看    
#27楼 2007-07-11 17:49 | winnerzone      
看过了~谢谢.
  回复  引用  查看    
#28楼[楼主] 2007-07-11 19:13 | Dflying Chen      
@winnerzone
:)

  回复  引用  查看    
#29楼 2007-08-20 19:53 | 里奥特      
@Dflying Chen
不知道还有什么地方要设置不,我今天第一次使用 WebService 做分类连动。

添加了

<asp:ScriptReference Path="~/SelectProductClass.asmx" />

和属性

[System.Web.Script.Services.ScriptService]

后,在页面上却总是提示我 SelectProductClass 未定义。不知道为什么。

  回复  引用  查看    
#30楼 2007-09-03 13:22 | Ceibahuang[未注册用户]
qq
  回复  引用    
#31楼 2007-11-26 16:40 | 傲剑无语[未注册用户]
不知道楼主还会不会来这,我想问下debugger的问题。
这个到底要怎么用?
用你的示例程序,但我F5调试它却不会在那里停啊。

  回复  引用    



发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

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

0 778672




相关文章:

相关链接: