flash+asp.net webServices入门教程
在Flash中调用WS时的身份验证_1:Hello
因为熟悉的WS的构造方式是基于Asp.net下的,下面所说的都是基于Asp.net的。
Flash作为UI层,有下列好处:
1、 不依赖于具体的平台
2、 轻量级,可以轻易的构造富客户端程序。
3、 可以给用户更好的体验。
但是,Flash在构建复杂的应用时,无法直接与数据库进行交互,必须依赖于其他的中间层进行,比如FlashRemtoing、PHP等等。各种方式都有优缺点。
在Flash与Asp.net进行交互时,最好的方式就是使用WebService。
下面构造第一个最简单的例子,从服务器端开始:
<%@ WebService Language="c#" Class="wsLearn.test" %>
//这句话声明了这是一个WebService。
using System;
using System.Web;
using System.Web.Services;
//创建WS时必须引用的类。
namespace wsLearn{
//ws “test”所在的命名空间
[WebService(Namespace="http://www.dxlschool.com/ws";)]
public class test:System.Web.Services.WebService{
public test(){
//do nothing
}
[WebMethod]
public string hello(){
return "你好!!";
}
就这样,一个最简单的WS构造好了,他只包含一个方法hello,把它放到你的支持asp.net的虚拟目录下,在浏览器中输入地址可以查看该ws运行的状况。
比如我在IE中输入如下地址http://localhost/ws/test.asmx
IE中会给出下列提示:
test
支持下列操作。有关正式定义,请查看服务说明。
Hello
点击”hello”,ws会返回一段XML文件。
<?xml version="1.0" encoding="utf-8" ?>
<string xmlns="http://www.dxlschool.com/ws";>你好!!</string>
下面我们在Flash中调用这个hello方法。
我使用的是Web 服务类来调用该ws 的hello方法。
/**
ActionScript Source File -- Created with SAPIEN Technologies PrimalScript 3.0
@class wsSessionTest_1
@package wsSessionTest_1.as
@author JimLee
@codehint
@example
@tooltip
*/
import mx.services.*;
//导入services包
var myws:WebService= new WebService("http://localhost/ws/test.asmx?wsdl";);
//使用WebService对象myws引用ws
//定义ws方法hello回调后的处理,参数result是ws的hello方法返回的值
// showSession_lb:lable组件
function hello(result) {
showSession_lb.text="从ws返回的消息:" result;
};
//testSession_bt:按钮
//使用PengingCall对象op_1在flash中代理ws的hello方法
this.testSession_bt.onPress=function(){
var op_1:PendingCall=myws. hello ();
op_1.onResult= hello;
}
需要注意的是,如果Web 服务类仅限 Flash Professional中使用,如果要在作品中使用Web服务类,必须导入Web服务类包,不然,是不会有响应的。
依次点击“窗口-其他面板-公用库-类”,打开公用库“类”,从中拖动WebSessionClasses组件到舞台上,将Web服务类包导入Fla,然后,你可以删除舞台上的WebSessionClasses组件的实例。
下面就可以测试一下你的swf了,如果不出以外,lable组件showSession_lb中将出现“从ws返回的消息:你好”。不过,要提醒的是:可要给你的lable组件留够足够的长度来显示信息啊!
在Flash中调用WS时的身份验证_2:输入与输出_1
下面让我们来了解一下flash中的Web服务类。
Web 服务类存在于mx.services包中。为了能够在运行时使用 Web 服务类,WebServiceClasses 组件必须位于 FLA 文件的库中。 Web服务类包含四个关键的类:WebService 类、PendingCall 类、Log 类、SOAPCall 类。其中, WebService 类、PendingCall 类与ws调用直接相关。通过WebService 类的构造器可以在Flash Player中返回指定WebService对象。如下面所示
Var myWebServiceObject:WebService = new WebService(wsdlURI);
参数wsdlURI指向引用的Web服务地址,比如“http://localhost/ws/test.asmx?wsdl”然后使用 PendingCall 类型的回调对象,在PendingCall回调对象的onResult方法中处理ws中指定方法的结果。比如:
var op_1:PendingCall=myws. hello ();
op_1.onResult= hello;
下面我们还是用一个例子来看一看Web服务类是怎么工作的。
说明:这个例子演示了在ws接受来自客户端的数字简单类型、日期和时间简单类型、bool类型、名称和字符串简单类型以及Array类型参数并返值。
首先还是构造服务器端的ws。
打开一个文本文件,声明一个WebService 处理指令
1、 如下:
<%@ WebService Language="c#" Codebehind="sample2.asmx.cs" Class="wsLearn.sample2" %>
命名为:sample2.asmx,放到虚拟目录http://localhost/ws/下。
Language 属性指示开发 XML Web services 所使用的编程语言。可以使用任何与 .NET 兼容的语言(如 Visual Basic .NET 或 Visual C#)来创建 XML Web services。与 .asmx 页关联的支持代码文件由 Codebehind 属性来指示。 Class 属性指示支持代码文件中用来实现 XML Web services 功能的类。
2、 新建一个cs文档:写入如下代码:
/* ======================================================================
C# Source File -- Created with SAPIEN Technologies Primalcode 3.0
NAME: sample2.asmx.cs
AUTHOR: JimLee , Dxl School
DATE : 2004-10-7
COMMENT: 这个例子演示了在ws接受来自客户端的数字简单类型、日期和时间简单类
型、bool类型、名称和字符串简单类型以及Array类型参数并返值。
====================================================================== */
using System;
using System.Web;
using System.Web.Services;
namespace wsLearn{
[WebService(Namespace="http://www.dxlschool.com/ws/";,Description="例2,演示ws方法的传值",Name="s2")]
public class sample2:System.Web.Services.WebService{
public sample2(){
//
}
[WebMethod]
public string GetUserName(string tName){
return "你好," tName;
}
}
}
注意下列几处代码:
[WebService(Namespace="http://www.dxlschool.com/ws/";,Description="例2,演示ws方法的传值",Name="s2")]
WebService 属性提供以下属性:
Description - 此属性的值包含描述性消息,此消息将在 XML Web services 的说明文件(例如服务说明和服务帮助页)生成后显示给 XML Web services 的潜在用户。
Name - 此属性的值包含 XML Web services 的名称。默认情况下,该值是实现 XML Web services 的类的名称。Name 属性标识 XML Web services 的 XML 限定名称的本地部分。Name 属性也用于在服务帮助页上显示 XML Web services 的名称。
Namespace - 此属性的值包含 XML Web services 的默认命名空间。XML 命名空间提供了一种在 XML 文档中创建名称的方法,该名称可由统一资源标识符 (URI) 标识。使用 XML 命名空间,可以唯一标识 XML 文档中的元素或属性。因而,在 XML Web services 的服务说明中,Namespace 被用作与 XML Web services 直接相关的 XML 元素的默认命名空间。如果不指定命名空间,就使用默认命名空间http: //tempuri.org/
public class sample2:System.Web.Services.WebService
类sample2继承自基类System.Web.Services.WebService,它提供了直接访问常见 ASP.NET 对象(如应用程序和会话状态的对象)的权限。需要注意的是该类必须是公共的,并且必须有一个公共的默认构造函数(不带参数的构造函数)。
[WebMethod]
通过在 Public 方法声明之前放置 WebMethod 属性可以指定在 XML Web services中可用的方法。Private 方法不能充当 XML Web services 的入口点,尽管它们可以采用相同的类并且 XML Web services 代码可以调用它们。 WebMethod 属性必须应用到可用作 XML Web services 一部分的每种公共方法中。
3、 将上面的cs文件命名为sample2.asmx.cs,用csc /t:library $File$将其编译为sample2.asmx.dll,在虚拟目录http: //localhost/ws/下新建子目录bin,将sample2.asmx.dll复制到http://localhost/ws/bin/下
下面就可以在浏览器中测试你的ws了:http://localhost/ws/sample2.asmx
或者http://localhost/ws/sample2.asmx?wsdl
下面让我们在flash中调用这个ws(现在它只包含一个方法GetUserName)。
1、 拖动WebSessionClasses组件到舞台上,将Web服务类包导入Fla,删除舞台上的WebSessionClasses组件的实例。
2、 拖动一个Button组件到舞台上,命名为:GetUN_bt,设置label属性为:“GetUserName”;
3、 添加如下动作脚本:
/**
ActionScript Class File -- Created with SAPIEN Technologies PrimalScript 3.0
@class wsSample_2
@package wsSample_2.as
@author JimLee
@codehint
@example
@tooltip
*/
import mx.services.*;
var myws:WebService=new WebService("http://localhost/ws/sample2.asmx?wsdl";);
function GetUserName(result){
trace("ws返回的值为:");
trace("///////////////////////////");
trace(result);
}
this.GetUN_bt.onPress=function(){
var op_1:PendingCall=myws.GetUserName("乔狗!!");
op_1.onResult=GetUserName;
}
赫赫,一点新东西都没有,只不过在PendingCall回调的方法中加入了参数值"乔狗!!"而已,就好像使用本地方法一样爽耶!
下面,你又可以测试一下了。
在Flash中调用WS时的身份验证_3:基本数据类型
在ws和flash客户端之间进行调用,最令人烦恼的莫过于两边同时支持的数据类型太少,下面,我们扩展一下前面的例子,看一看他们之间都可以同时使用那些数据类型。
首先我们来看一看Number类型:
XML 架构类型支持的数字简单类型很多,在flash中都作为Number类型处理。下面我们对sample2.asmx.cs进行小小的修改:增加一个方法IncAB,如下:
[WebMethod]
public int IncAB(int A,int B){
return A B;
}
此图片仅显示局部,请点击查看完整图片
在flash的web服务窗口中可以查看IncAB方法的参数和返回值的类型都是整型。
对wsSample_2.as也作一点小小的修改:
function IncAB(result){
trace("ws方法IncAB返回的值为:");
trace("///////////////////////////");
trace(result);
}
……
this.incAB_bt.onPress=function(){
var a:Number=34;
var b:Number=56;
var op_2:PendingCall=myws.IncAB(a,b);
op_2.onResult=IncAB;
}
测试一下,output窗口会返回
ws方法IncAB返回的值为:
///////////////////////////
90
如果我们将a和b的值分别设置为一个小数了?比如:56.4之类?output将返回
Error opening URL http://localhost/ws/sample2.asmx
如果你想让提示更加友好,web服务类提供了容错处理,但是不是我们这里要讨论的内容,后面再说。
对于其他的数字简单类型,都和这个差不多,可以自己尝试一下。
下面是扩充后的sample2.asmx.cs文件,添加了IncAB、GetNow、PassDate、PassBool这四个web方法:
/* ======================================================================
C# Source File -- Created with SAPIEN Technologies Primalcode 3.0
NAME: sample2.asmx.cs
AUTHOR: JimLee , Dxl School
DATE : 2004-10-7
COMMENT: 这个例子演示了在ws接受来自客户端的数字简单类型、日期和时间简单类
型、bool类型、名称和字符串简单类型以及Array类型参数并返值。
====================================================================== */
using System;
using System.Web;
using System.Web.Services;
namespace wsLearn{
[WebService(Namespace="http://www.dxlschool.com/ws/";,Description="例2,演示ws方法的传值",Name="s2") ]
public class sample2:System.Web.Services.WebService{
public sample2(){
//
}
[WebMethod]
public string GetUserName(string tName){
return "你好," tName;
}
[WebMethod]
public int IncAB(int A,int B){
return A B;
}
[WebMethod]
public DateTime GetNow(){
return DateTime.Now;
}
[WebMethod]
public DateTime PassDate(DateTime dt){
return dt;
}
[WebMethod]
public bool PassBool(bool bl){
return bl;
}
}
}
扩充后的wsSample_2.as:
/**
ActionScript Class File -- Created with SAPIEN Technologies PrimalScript 3.0
@class wsSample_2
@package wsSample_2.as
@author JimLee
@codehint
@example
@tooltip
*/
import mx.services.*;
var myws:WebService=new WebService("http://localhost/ws/sample2.asmx ?wsdl");
function GetUserName(result){
trace("ws返回的值为:");
trace("///////////////////////////");
trace(result);
}
function IncAB(result){
trace("ws方法IncAB返回的值为:");
trace("///////////////////////////");
trace(result);
}
function GetNow(result){
trace("ws方法GetNow返回的值为:");
trace("/////////////////////////");
trace(result);
}
function PassDate(result){
trace("ws方法PassDate返回的值为:");
trace("/////////////////////////");
trace(result);
}
function PassBool(result){
trace("ws方法PassBool返回的值为:");
trace("/////////////////////////");
trace(result);
}
this.GetUN_bt.onPress=function(){
var op_1:PendingCall=myws.GetUserName("乔狗!!");
op_1.onResult=GetUserName;
}
this.incAB_bt.onPress=function(){
var a:Number=34;
var b:Number=56;
var op_2:PendingCall=myws.IncAB(a,b);
op_2.onResult=IncAB;
}
this.GetNow_bt.onPress=function(){
var op_3:PendingCall=myws.GetNow();
op_3.onResult=GetNow;
}
this.PassDT_bt.onPress=function(){
var dt:Date=new Date (77, 4, 2);
var op_4:PendingCall=myws.PassDate(dt);
op_4.onResult=PassDate;
}
this.PassBool_bt.onPress=function(){
var bl:Boolean=true;
var op_5:PendingCall=myws.PassBool(bl);
op_5.onResult=PassBool;
}
例子很简单,不一一注释了。
在Flash中调用WS时的身份验证_4:数组
数组可能是各种语言中最常见的一种数据类型了。下面我们来看一看在Flash与ws交互时如何处理数组(或者“近似”数组的数据类型)。
还是让我们借着对sample2.asmx.cs修修补补吧:在sample2.asmx.cs中增加一个web方法:
[WebMethod]
public string[] GetArray_1(){
string[] strArr={"乔狗","刘鹏","陈波","张成平","费明","陈刚"};
return strArr;
}
该方法返回一个字符串数组,编译之,在flash的web服务窗口中可以看到
此图片仅显示局部,请点击查看完整图片
该方法返回的数据类型。
下面让我们在AS脚本中处理接受过来的数据:
function GetArray_1(result){
trace("ws方法GetArray_1返回的值为:");
trace("/////////////////////////");
for (var i=0;i<result.length;i ){
trace(i ":" result[ i ]);
}
}
咳!和本地处理数组一点区别都没有。
实际上,在.net中我们对原始Array数据型用的不多。更多的是使用System.Collections命名空间中的一些较“高级”的数据类型: ArrayList、Hashtable、HybridDictionary等等。在ws flash交互中,他们的处理和数组类似,不过,在flash 也提供了一些复杂的类、API让我们更简单方便的处理这些较复杂的数据类型。
先看一看ArrayList的一个最简单的应用,在sample2.asmx.cs中增加web方法GetArray_2:
[WebMethod(Description="数组的调用:ArrayList")]
public ArrayList GetArray_2(){
ArrayList strArr=new ArrayList();
int i=0;
for (i=0;i<100;i ){
strArr.Add("strArr[" i "]");
}
return strArr;
}
Flash客户端的处理与处理普通数组无异,就不列出代码了。
此图片仅显示局部,请点击查看完整图片
上面是一个复杂数据的处理实例,如上图所示。
首先来看一看服务器端的实现:首先在sample2.asmx.cs中增加web方法GetArray_3:
[WebMethod(Description="数组的调用,包含对象")]
public Car[] GetArray_3(){
Car HG=new Car("皇冠",2004);
Car JM=new Car("佳美",2003);
Car YK=new Car("雅阁",2004);
Car BJS=new Car("毕加索",2002);
Car[] carArr={HG,JM,YK,BJS};
return carArr;
}
需要注意这里的Car类来自哪里呢?下面是Car类的实现:
[Serializable]
public class Car{
//声明字段model、yearBuilt;
public string model;
public int yearBuilt;
//定义构造器
public Car(string model,int yearBuilt){
this.model=model;
this.yearBuilt=yearBuilt;
}
public Car(){
}
}
千万注意:Car类一定要序列化!!
在浏览器中测试该方法,可以返回下列XML文件
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfCar xmlns:xsd="http://www.w3.org/2001/XMLSchema"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; xmlns="http://www.dxlschool.com/ws/";>
<Car>
<model>皇冠</model>
<yearBuilt>2004</yearBuilt>
</Car>
<Car>
<model>佳美</model>
<yearBuilt>2003</yearBuilt>
</Car>
<Car>
<model>雅阁</model>
<yearBuilt>2004</yearBuilt>
</Car>
<Car>
<model>毕加索</model>
<yearBuilt>2002</yearBuilt>
</Car>
</ArrayOfCar>
再让我们回到Flash2004,看一看客户端的处理,非常的简单:
function GetArray_3(result){
//定义一个数组接受ws传值
var myDB:Array=result;
//将数组myDB与DataGrid组件gb_main绑定
gb_main.dataProvider=myDB;
}
……
this.dbBind2_bt.onPress=function(){
var op_7:PendingCall=myws.GetArray_3();
op_7.onResult=GetArray_3;
}
大功告成,赫赫。
前面我们做了个从WS中获取数据填充Flash的DataGrid的例子。在实践中,很多时候,我们需要把在DataGrid中修改过的数据再一次传递回服务器,在服务器上将这些数据持久化。
在flash中,有很多的方法可以把数据传回服务器保存:LoadVars,拼接xml等等,操作的过程繁琐、不易用,还受到很多限制,使用Flash WS的话,还是那句话,非常的方便。还是让我们用例子来说话。
1、 修改sample2.asmx.cs,增加Web方法GetArray_4,该web方法有一个参数,数组tCar。
[WebMethod(Description="接受客户端传递过量数组")]
public string GetArray_4(Car[] tCar){
string tStr="";
for (int i=0;i<tCar.Length;i ){
tStr=tStr "; " tCar.model;
}
return tStr;
}
2、 修改Flash如下:
function GetArray_4(result){
trace("ws方法GetArray_4返回的值为:");
trace("/////////////////////////");
trace(result);
}
……
this.dbBind3_bt.onPress=function(){
//trace(gb_main.dataProvider.length);
var i:Number=0;
var tCar:Array=new Array();
tCar=gb_main.dataProvider;
var op_8:PendingCall=myws.GetArray_4(tCar);
op_8.onResult=GetArray_4;
}
运行,output窗口会提示:
Error opening URL http://localhost/ws/sample2.asmx
为什么会这样呢?原因出在DataGrid组件的dataProvider上,你可以跟踪一下dataProvider提供的数组,会发现 dataProvider不知道为什么,会增加一些内容数据类型未知的object,但是毫无疑问,对象数组Car[]是可以通过Flash传递到ws 的。
下面是修改后测试通过的代码:
/* ======================================================================
C# Source File -- Created with SAPIEN Technologies Primalcode 3.0
NAME: sample2.asmx.cs
AUTHOR: JimLee , Dxl School
DATE : 2004-10-7
COMMENT: 这个例子演示了在ws接受来自客户端的数字简单类型、日期和时间简单类
型、bool类型、名称和字符串简单类型以及Array类型参数并返值。
====================================================================== */
using System;
using System.Collections;
using System.Web;
using System.Web.Services;
namespace wsLearn{
[WebService(Namespace="http://www.dxlschool.com/ws/";,Description="例2,演示ws方法的传值",Name="s2")]
public class sample2:System.Web.Services.WebService{
public sample2(){
//
}
[WebMethod]
public string GetUserName(string tName){
return "你好," tName;
}
[WebMethod]
public int IncAB(int A,int B){
return A B;
}
[WebMethod]
public DateTime GetNow(){
return DateTime.Now;
}
[WebMethod]
public DateTime PassDate(DateTime dt){
return dt;
}
[WebMethod]
public bool PassBool(bool bl){
return bl;
}
[WebMethod]
public string[] GetArray_1(){
string[] strArr={"乔狗","刘鹏","陈波","张成平","费明","陈刚"};
return strArr;
}
[WebMethod(Description="数组的调用:ArrayList")]
public ArrayList GetArray_2(){
ArrayList strArr=new ArrayList();
int i=0;
for (i=0;i<100;i ){
strArr.Add("strArr[" i "]");
}
return strArr;
}
[WebMethod(Description="数组的调用,包含对象")]
public Car[] GetArray_3(){
Car HG=new Car("皇冠",2004);
Car JM=new Car("佳美",2003);
Car YK=new Car("雅阁",2004);
Car BJS=new Car("毕加索",2002);
/*ArrayList carArr=new ArrayList();
carArr.Add(HG);
carArr.Add(JM);
carArr.Add(YK);
carArr.Add(BJS);*/
Car[] carArr={HG,JM,YK,BJS};
return carArr;
}
[WebMethod(Description="接受客户端传递过量数组")]
public string GetArray_4(Car[] tCar){
string tStr="";
for (int i=0;i<tCar.Length;i ){
tStr=tStr "; " tCar.model;
}
return tStr;
}
}
[Serializable]
public class Car{
//声明字段model、yearBuilt;
public string model;
public int yearBuilt;
//定义构造器
public Car(string model,int yearBuilt){
this.model=model;
this.yearBuilt=yearBuilt;
}
public Car(){
}
}
}
/**
ActionScript Class File -- Created with SAPIEN Technologies PrimalScript 3.0
@class wsSample_2
@package wsSample_2.as
@author JimLee
@codehint
@example
@tooltip
*/
import mx.services.*;
gb_main.vScrollPolicy="off";
var myws:WebService=new WebService("http://localhost/ws/sample2.asmx?wsdl";);
function GetUserName(result){
trace("ws返回的值为:");
trace("///////////////////////////");
trace(result);
}
function IncAB(result){
trace("ws方法IncAB返回的值为:");
trace("///////////////////////////");
trace(result);
}
function GetNow(result){
trace("ws方法GetNow返回的值为:");
trace("/////////////////////////");
trace(result);
}
function PassDate(result){
trace("ws方法PassDate返回的值为:");
trace("/////////////////////////");
trace(result);
}
function PassBool(result){
trace("ws方法PassBool返回的值为:");
trace("/////////////////////////");
trace(result);
}
function GetArray_1(result){
trace("ws方法GetArray_1返回的值为:");
trace("/////////////////////////");
for (var i=0;i<result.length;i ){
trace(i ":" result);
}
}
function GetArray_3(result){
var myDB:Array=result;
gb_main.dataProvider=myDB;
trace(gb_main.dataProvider.length);
}
function GetArray_4(result){
trace("ws方法GetArray_4返回的值为:");
trace("/////////////////////////");
trace(result);
}
this.GetUN_bt.onPress=function(){
var op_1:PendingCall=myws.GetUserName("乔狗!!");
op_1.onResult=GetUserName;
}
this.incAB_bt.onPress=function(){
var a:Number=34;
var b:Number=56;
var op_2:PendingCall=myws.IncAB(a,b);
op_2.onResult=IncAB;
}
this.GetNow_bt.onPress=function(){
var op_3:PendingCall=myws.GetNow();
op_3.onResult=GetNow;
}
this.PassDT_bt.onPress=function(){
var dt:Date=new Date (77, 4, 2);
var op_4:PendingCall=myws.PassDate(dt);
op_4.onResult=PassDate;
}
this.PassBool_bt.onPress=function(){
var bl:Boolean=true;
var op_5:PendingCall=myws.PassBool(bl);
op_5.onResult=PassBool;
}
this.dbBind1_bt.onPress=function(){
var op_6:PendingCall=myws.GetArray_1();
//var op_6:PendingCall=myws.GetArray_2();
op_6.onResult=GetArray_1;
}
this.dbBind2_bt.onPress=function(){
var op_7:PendingCall=myws.GetArray_3();
op_7.onResult=GetArray_3;
}
this.dbBind3_bt.onPress=function(){
//trace(gb_main.dataProvider[1]);
trace(gb_main.dataProvider.length);
var i:Number=0;
var tCar:Array=new Array();
for (i=0;i<4;i ){
tCar.push(gb_main.dataProvider);
}
//tCar=gb_main.dataProvider;
for (i=0;i<(tCar.length/2-1);i ){
trace(tCar.model);
}
var op_8:PendingCall=myws.GetArray_4(tCar);
op_8.onResult=GetArray_4;
}
