Flex數據交互經常使用的有三種方式:WebService、HttpService以及Remoting。html
WebService方式已在這篇文章中給出,這篇文章主要講解以Remoting方式進行數據交互,Remoting是基於AMF的數據交互,速度及性能均較WebService好,是公認最有效率的方法。json
FluorineFx是一個開源庫,提供了一種在.NET Framework下對Flex/Flash的遠程調用過程。FluorineFx官網地址在這,FluorineFx能夠在這下載。 數組
下載安裝後,會在vs2008中自動增長兩處模板:FluorineFx ServicesLibrary與FluorineFx ASP.NET Web Site。服務器
接下來演示如何利用FluorineFx進行Flex與ASP.NET數據交互。ide
(1)新建FluorineFx ServicesLibrary類庫,以下圖:函數
(2)在剛纔創建的解決方案FlexRemotingDemo中,添加FluorineFx ASP.NET Web Site網站,以下圖:性能
該網站會自動引入FlexRemotingDemo.dll:flex
在類庫FlexRemotingDemo的Sample.cs文件中能夠添加本身的函數: 網站
/// <summary> /// 得到監測站信息(14個監測站) /// </summary> /// <returns></returns> public string getStationInfo() { string json = ""; DataTable dt = new DataTable(); dt = helper.GetStationInfo(); if (dt != null) { json = ConverTableToJSON(dt); } return json; }
將網站發佈到IIS下:運行便可看到結果:this
(3)修改WEB-INF\flex下的services-config.xml配置文件:
<channels>
<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
<endpoint uri="http://localhost/FlexRemotingDemo/Gateway.aspx" class="flex.messaging.endpoints.AMFEndpoint"/>
<properties>
<!-- <legacy-collection>true</legacy-collection> -->
</properties>
</channel-definition>
<!--
<channel-definition id="my-rtmp" class="mx.messaging.channels.RTMPChannel">
<endpoint uri="rtmp://{server.name}:2037" class="flex.messaging.endpoints.RTMPEndpoint"/>
<properties>
<idle-timeout-minutes>20</idle-timeout-minutes>
</properties>
</channel-definition>
-->
</channels>
(1)新建Flex項目:
(2)配置Flex項目FlexRemotingDemo:
(3)編寫程序代碼:
<?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" minWidth="955" minHeight="600">
<fx:Declarations> <mx:RemoteObject id="RO" destination="fluorine" source="ServiceLibraryDemo.Sample"> <mx:method name="getStationInfo" result="onResult(event)"/> </mx:RemoteObject> </fx:Declarations> <fx:Script> <![CDATA[ import mx.events.FlexEvent; import mx.rpc.AbstractOperation; import mx.rpc.events.ResultEvent;
protected function btn1_clickHandler(event:MouseEvent):void { RO.getStationInfo(); } public function onResult(evt:ResultEvent):void{ txt1.text=evt.result.toString(); } ]]> </fx:Script> <s:Button id="btn1" label="得到14個監測站信息" x="630" y="50" click="btn1_clickHandler(event)"/> <s:TextArea id="txt1" x="20" y="40" width="600" />
</s:Application>
運行結果以下:
源碼在這下載。
源碼下載。
如上面,用起來相對比較麻煩,封裝RemoteObject以方便使用,這篇文章給出了相應的封裝方法,我略做改動以適用本程序。
(1)CYMRemoteObject.cs
package components { /** * @author chenyuming */ import mx.controls.Alert; import mx.rpc.AbstractOperation; import mx.rpc.AsyncToken; import mx.rpc.CallResponder; import mx.rpc.Responder; import mx.rpc.events.FaultEvent; import mx.rpc.events.ResultEvent; import mx.rpc.remoting.mxml.RemoteObject; public class CYMRemoteObject extends RemoteObject { public static const DEFAULT_DESTINATION:String = "fluorine"; public static const DEFAULT_SOURCE:String = ""; public function CYMRemoteObject(source:String,destination:String = DEFAULT_DESTINATION) { this.source = source; super(destination); } public function call(methodName:String, callback:Function, ...args):void { var method:AbstractOperation = this.getOperation(methodName); //爲了方便起見,若是有多個參數的話就把參數包成一個Array,在J2EE端使用Object[]來獲取參數 method.arguments = args; var call:AsyncToken = method.send(); call.userDefinedCallback = callback; call.addResponder(new Responder(resultCallback, faultCallback)); } public function resultCallback(event:ResultEvent):void { var callback:Function = event.token.userDefinedCallback as Function; if (callback != null) { var result:CYMRemoteObjectResult = new CYMRemoteObjectResult(); result.error = false; result.result = event.result; callback(result); } } public function faultCallback(event:FaultEvent):void { var callback:Function = event.token.userDefinedCallback as Function; if (callback != null) { var result:CYMRemoteObjectResult = new CYMRemoteObjectResult(); result.error = true; result.errorMessage = event.fault.toString(); callback(result); } } } }
CYMRemoteObjectResult.cs
package components { /** * @author chenyuming */ public class CYMRemoteObjectResult { public function CYMRemoteObjectResult() { } public var error:Boolean = false; public var errorMessage:String = null; public var result:Object = null; } }
(2)引用方式
protected function btn1_clickHandler(event:MouseEvent):void { var ro:CYMRemoteObject = new CYMRemoteObject("ServiceLibraryDemo.Sample", "fluorine"); ro.call("getStationInfo",onResult3); //RO.getStationInfo(); } public function onResult3(evt:CYMRemoteObjectResult):void { if(evt.error) { Alert.show(evt.errorMessage); } else { txt1.text=evt.result.toString(); } }
上面利用getStationInfo返回的是json類型,有時服務器端更喜歡直接返回DataTable類型以便於直接綁定Flex中形如DataGrid的容器,下面演示數據交互類型爲DataTable:
(1)服務器端:Sample.cs中增長函數getStationInfo2
/// <summary> /// 得到監測站信息(14個監測站) /// </summary> /// <returns></returns> public DataTable getStationInfo2() { DataTable dt = new DataTable(); dt = helper.GetStationInfo(); return dt; }
(2)客戶端Flex:FlexRemotingDemo.mxml中添加DataGrid容器
<s:Button id="btn2" label="得到14個監測站信息" x="630" y="199" click="btn2_clickHandler(event)"/> <s:DataGrid id="dg" x="20" y="199" width="600" height="401" dataProvider="{arrColl}" requestedRowCount="14" textAlign="center"> <s:columns> <s:ArrayList> <s:GridColumn width="{0.21 * this.dg.width}" dataField="jcd_name" headerText="監測點名稱"></s:GridColumn> <s:GridColumn width="{0.13 * this.dg.width}" dataField="ssly" headerText="所屬流域"></s:GridColumn> <s:GridColumn width="{0.30 * this.dg.width}" dataField="zyzbytr" headerText="主要植被與土壤"></s:GridColumn> <s:GridColumn width="{0.10 * this.dg.width}" dataField="xqsl" headerText="小區數量"></s:GridColumn> <s:GridColumn width="{0.13 * this.dg.width}" dataField="fjswylz" headerText="附近水文雨量站"></s:GridColumn> <s:GridColumn width="{0.13 * this.dg.width}" dataField="jgsj" headerText="竣工時間"></s:GridColumn> </s:ArrayList> </s:columns> </s:DataGrid>
利用封裝好的RemoteObejct對象CYMRemoteObject來綁定DataGrid:
[Bindable] private var arrColl:ArrayCollection = new ArrayCollection(); protected function btn2_clickHandler(event:MouseEvent):void { var ro:CYMRemoteObject = new CYMRemoteObject("ServiceLibraryDemo.Sample","fluorine"); ro.call("getStationInfo2",onResult2); } public function onResult2(evt:CYMRemoteObjectResult):void { if(evt.error) { Alert.show(evt.errorMessage); } else { arrColl.removeAll(); // 獲取列名 var columnName:Array = evt.result.serverInfo.columnNames as Array; //獲取數據 var columnData:Array = evt.result.serverInfo.initialData as Array; //列數組 var columns:Array=new Array(); for(var rowIndex:int = 0; rowIndex < columnData.length; rowIndex++) { var obj:Object = new Object(); for(var colIndex:int = 0; colIndex < columnName.length; colIndex++) { var key:String = columnName[colIndex].toString(); var value:String = columnData[rowIndex][colIndex].toString(); obj[key] = value; } arrColl.addItem(obj); } } }
運行結果: