zoukankan      html  css  js  c++  java
  • Flex4中使用WCF

    虽然flex跟.net交互的首选是FluorineFx,但是如果在某些特定情况下(比如服务端是现成的,不允许修改,或者服务端开发方不懂FluorineFx为何物),这时webService还是挺有用的。

    WebService完全可以用"以BasicHttpBinding方式运行的WCF"代替。经过我的实际测试:对于基本类型(比如int,string,datetime以及它们对应的arrry以list),flex调用时能正确识别并“翻译”成as3中对应的int,String,Date以及Array类型,而复杂类型(比如自己在c#中定义的实体类或DataTable),flex调用时会报错,这类复杂类型我建议在wcf中用序列化技术处理成String后再返回。

    考虑到xml格式序列化后的信息量比较大,我倾向于选择json这种轻量级的格式,而且在.net4.0中新增了System.Runtime.Serialization.Json;能处理大多数的复杂对象序列化(但是DataTable处理不了)

    为了方便起见,我把一些序列化/反序列化的操作封装了一下:
    using System;
    using System.IO;
    using System.Runtime.Serialization.Json;
    using System.Text;
    using System.Data;
    
    namespace Helper
    {
        public static class Utils
        {
            /// <summary>
            /// 将对象序列化成json字符串(注:obj的类定义中要加正确的可序列化标志)
            /// </summary>
            /// <param name="obj"></param>
            /// <returns></returns>
            public static string ToJsonString(object obj)
            {
                string result = string.Empty;
                DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(obj.GetType());
    
                using (MemoryStream ms = new MemoryStream())
                {
                    jsonSerializer.WriteObject(ms, obj);
                    result = Encoding.UTF8.GetString(ms.ToArray());
                }
    
                return result;
            }
    
            /// <summary>
            /// json字符串反序列为对象
            /// </summary>
            /// <param name="jsonString"></param>
            /// <param name="objType"></param>
            /// <returns></returns>
            public static Object ToJsonObject(string jsonString, Type objType)
            {
                Object result = null;
                DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(objType);
    
                using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)))
                {
                    result = jsonSerializer.ReadObject(ms);
                }
    
                return result;
            }
    
            /// <summary>
            /// 将DataTable序列化成json字符串
            /// </summary>
            /// <param name="dt"></param>
            /// <returns></returns>
            public static string ToJsonString(this DataTable dt)
            {
              
                StringBuilder JsonString = new StringBuilder();
                //Exception Handling        
                if (dt != null && dt.Rows.Count > 0)
                {
                    JsonString.Append("{ ");
                    JsonString.Append("\"Rows\":[ ");
                    for (int i = 0; i < dt.Rows.Count; i++)
                    {
                        JsonString.Append("{ ");
                        for (int j = 0; j < dt.Columns.Count; j++)
                        {
                            if (j < dt.Columns.Count - 1)
                            {
                                JsonString.Append("\"" + dt.Columns[j].ColumnName.ToString().Replace("\"", "\\\"") + "\":" + "\"" + dt.Rows[i][j].ToString().Replace("\"", "\\\"") + "\",");
                            }
                            else if (j == dt.Columns.Count - 1)
                            {
                                JsonString.Append("\"" + dt.Columns[j].ColumnName.ToString().Replace("\"", "\\\"") + "\":" + "\"" + dt.Rows[i][j].ToString().Replace("\"", "\\\"") + "\"");
                            }
                        }
                        /**/
                        /*end Of String*/
                        if (i == dt.Rows.Count - 1)
                        {
                            JsonString.Append("} ");
                        }
                        else
                        {
                            JsonString.Append("}, ");
                        }
                    }
                    JsonString.Append("]}");
                    return JsonString.ToString();
                }
                else
                {
                    return null;
                }
            }
        }
    }
    
    不过,在开始正文之前,先提醒一下System.Runtime.Serialization.Json在序列化中要注意的问题:
    比如有一个类Person,定义如下:
        [Serializable]
        public class Person 
        {
            private string _name;
            private int _age;
            private float _salary;
    
            public string Name { set { _name = value; } get { return _name; } }        
            public int Age { set { _age = value; } get { return _age; } }        
            public float Salary { set { _salary = value; } get { return _salary; } }
            
        }
    
    对象
    Person p = new Person(){Age=30, Name="jimmy.yang", Salary=5000};
    
    序列后的字符串为
    {"_age":30,"_name":"jimmy.yang","_salary":5000}

    注意:这里并不是我所期待的{"Age":30,"Name":"jimmy.yang","Salary":5000},其实出现这样的结果也可以理解,因为属性的set,get内部就是方法调用,因此最终序列化的只是私有字段。但是如果把[Serializable]标志去掉,确能得到正确的结果:{"Age":30,"Name":"jimmy.yang","Salary":5000} 不知道这个算不算是System.Runtime.Serialization.Json的一个bug.
     
    实际flex应用中,用于传输的实体类99%以上保存的只是一些常规的基元类型(即int,string,date之类),所以为了避免上面提到的问题,我建议:
    1、实体类定义中只使用基本类型,去掉[Serializable]
    2、或者直接把实例成员用类似public string Name;的方式暴露出来,不过估计大数多酷爱OO的同学们要吐血了.

    ok,切入正题吧:
    1、先创建一个asp.net项目,然后添加一个wcf service,文件命名为:Sample.svc,对应的后端代码文件Sample.svc.cs内容如下:
    using System.Collections.Generic;
    using System.Data;
    using System;
    using Helper;
    using Entity;
    
    namespace WcfApp
    {
        // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Sample" in code, svc and config file together.
        public class Sample : ISample
        {
            
    
            public string ObjectTest()
            {
                return Utils.ToJsonString(new Person() { Age=30, Name="jimmy.yang", Salary=3000 });
            }
    
    
            public string DataTableTest()
            {
                DataTable tbl = new DataTable();
                tbl.Columns.Add("Name");
                tbl.Columns.Add("Age");
                tbl.Rows.Add("Jimmy.Yang", 30);
                tbl.Rows.Add("Mike", 20);
                return tbl.ToJsonString();
            }
    
    
            public string ListObjectTest()
            {
                return Utils.ToJsonString(
                    new List<Person>() { 
                        new Person() { Age = 20, Name = "张三", Salary = 5000 }, 
                        new Person() { Age = 30, Name = "李四", Salary = 8000 } 
                    }
                );
            }
        }
    }
    

    2、创建flex项目,然后在Data/Services面板中,添加一个webSerivce的引用
    点击Next之后,出现下面的界面
    设置wcf所在的WSDL URI后,一路next,最终Data/WebServices面板会变成下面这样
    注意上图中右侧工具栏上的几个小按钮,自己去试试吧,会有意外发现哦
    同时flex会生成几个as类文件(类似于wcf中svcutil.exe在client端自动生成的cs文件)
    剩下的事情,就很容易了,在mxml中测试一番,代码如下:
    <?xml version="1.0" encoding="utf-8"?>
    <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    			   xmlns:s="library://ns.adobe.com/flex/spark" 
    			   xmlns:mx="library://ns.adobe.com/flex/mx"  xmlns:sample="services.sample.*">
    	
    
    	<fx:Script>
    		<![CDATA[
    			
    			import com.adobe.serialization.json.JSONDecoder;			
    			import mx.controls.Alert;
    			import mx.rpc.events.FaultEvent;
    			import mx.rpc.events.ResultEvent;			
    			import valueObjects.Person;
    			
    			
    			private function dataTableTest():void
    			{
    				DataTableTestResult.token = sample.DataTableTest();
    				DataTableTestResult.addEventListener(ResultEvent.RESULT,onDataTableTestResult);
    				DataTableTestResult.addEventListener(FaultEvent.FAULT,onDataTableTestFault);
    			}
    			
    			private function onDataTableTestFault(e:FaultEvent):void
    			{
    				Alert.show("dataTableTest调用失败,result="+ e);
    				trace("dataTableTest.Fault=",e);
    			}
    			
    			private function onDataTableTestResult(e:ResultEvent):void
    			{
    				this.txtDataTable.text = "dataTableTest调用成功,结果:" + e.result;
    			}
    			
    			
    			private function listObjectTest():void
    			{
    				ListObjectTestResult.token = sample.ListObjectTest();
    				ListObjectTestResult.addEventListener(ResultEvent.RESULT,onListObjectTestResult);
    				ListObjectTestResult.addEventListener(FaultEvent.FAULT,onListObjectFault);
    			}
    			
    			private function onListObjectTestResult(e:ResultEvent):void
    			{
    				this.txtList.text = "listObjectTest调用成功,结果:" + e.result;
    				var jsonDecoder:JSONDecoder = new JSONDecoder(e.result.toString(),true);
    				var obj:Object = jsonDecoder.getValue();
    				//把结果转化为强类型的集合
    				var list:Vector.<Person> = new Vector.<Person>();
    				for(var i:int=0;i<obj.length;i++)
    				{
    					list[i] = new Person(obj[i].Name,obj[i].Age,obj[i].Salary);
    				}				
    				trace(list);				
    			}
    			
    			private function onListObjectFault(e:FaultEvent):void
    			{
    				Alert.show("listObjectTest调用失败,result="+ e);
    				trace("listObjectTest.Fault=",e);
    			}			
    			
    			private function objectTest():void
    			{
    				ObjectTestResult.token = sample.ObjectTest();
    				ObjectTestResult.addEventListener(ResultEvent.RESULT,onObjectTestResult);
    				ObjectTestResult.addEventListener(FaultEvent.FAULT,onObjectTestFault);
    			}
    			
    			private function onObjectTestResult(e:ResultEvent):void
    			{
    				this.txtObject.text = "objectTest调用成功,返回值:" + e.result;
    				var jsonDecoder:JSONDecoder = new JSONDecoder(e.result.toString(),true);
    				var obj:Object = jsonDecoder.getValue();
    				var p:Person = new Person(obj.Name,obj.Age,obj.Salary);					
    				this.txtObject.text += "\n" + "p.Age=" + p.Age + ",p.Name=" + p.Name + ",p.Salary=" + p.Salary;
    			}
    			
    			private function onObjectTestFault(e:FaultEvent):void
    			{				
    				this.txtObject.text = "objectTest调用失败,原因="+ e;
    			}			
    			
    			private function doClick():void
    			{				
    				objectTest();				
    				listObjectTest();
    				dataTableTest();
    			}	
    			
    		]]>
    	</fx:Script>
    	<fx:Declarations>
    		<s:CallResponder id="ArrayTestResult"/>
    		<sample:Sample id="sample" fault="Alert.show(event.fault.faultString + '\n' + event.fault.faultDetail)" showBusyCursor="true"/>
    		<s:CallResponder id="DataTableTestResult"/>
    		<s:CallResponder id="ListObjectTestResult"/>		
    		<s:CallResponder id="ObjectTestResult"/>	
    	</fx:Declarations>
    	<s:Panel right="10" left="10" bottom="10" top="10" title="WCF 调用实例">
    		<s:layout>
    			<s:BasicLayout/>
    		</s:layout>
    		<mx:VDividedBox left="10" bottom="40" right="10" top="0">
    			<s:TextArea height="33%" width="100%" id="txtObject">
    				
    			</s:TextArea>
    			<s:TextArea height="33%" width="100%" id="txtList">
    				
    			</s:TextArea>
    			<s:TextArea height="33%" width="100%" id="txtDataTable">
    				
    			</s:TextArea>
    		</mx:VDividedBox>
    		<s:Button label="Call Wcf" horizontalCenter="0" id="btnCall" click="doClick()"  bottom="10"/>
    	</s:Panel>
    </s:Application>
    
    后记:在实际开发中发现flex ide环境对于wcf的wsdl解析要比asmx慢不止N倍,但是一旦解析完成,生成相应的as类后,在运行时二耆速度相同。
    作者:菩提树下的杨过
    出处:http://yjmyzz.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    分区调整教程
    ArcServer10.1系列产品之ArcGIS Web Adaptor (IIS)
    初次登录github
    java中的关键字
    《构建之法》第二章学习有感
    《构建之法》第一章节学后有感
    第一次写博客
    HashMap 扩容分析
    ArrayList的扩容机制
    古籍研究社系列第6部《迟来的翅膀》读后感……吗?
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/2010228.html
Copyright © 2011-2022 走看看