silverlight获取外部数据的另一种选择:FluorineFx
2010-07-25 11:10
471 查看
Silverlight从其它系统获取外部数据的常规途径无非下面2种:
1、直接远程加载文本或xml文件 (直接请求ashx/aspx,然后在ashx/aspx上输出信息也可以归入这一类)
2、通过wcf/webService取得数据
(当然,sl跟本机的sl之间也能交换数据,但这个用处有限,此外通过socket也能拿到数据,但是socket要玩好并不容易,难度系数有点高,本文不做讨论)
而返回的数据格式,最常用的通常为"xml"、"json字符串"(或普通字符串) 或 "最原始的Stream"
今天在学习FluorineFx(一个开源的免费项目),并查看它的演示示例时,意外发现FluorineFx也支持silverlight!
与webService采用的soap协议不同:FluorineFx支持Adobe的AMF0,AMF3,RTMP协议,能方便的与Adobe几乎所有的通讯技术交互,这为silverlight与flash/flex交互提供了可能。(详见百度百科FluorineFX http://baike.baidu.com/view/1654458.htm?fr=ala0_1)
下面简单说下silverlight中使用FluorineFx的大概步骤:
基本上 silverlight本身只是一种UI技术,自身并无太强的的数据处理能力(独立存储虽然提供了数据存储和检索能力,但能力实在有限),要获取数据只能借助其它系统或技术,所以我们先把其它系统做好:
1、先用VS.Net(我用的是vs2010)创建一个Library项目,起名为ServiceLib,并在里面创建一个TestLib.cs的类,代码如下:
当然,这个项目要引用FluorineFx程序集,该项目的主要用意在于把"取数据"的业务逻辑封装在这一层,以方便重用。
2、再创建一个webApplication,起名为WebApp,同样要添加FluorineFx.dll的引用
2.1 然后创建一个名为Gateway.aspx的文件,这样就行了,不用添加任何多余的代码(这个文件作为调用FluorineFx的网关)
2.2 在根目录下,创建目录Web-INF/flex (即二层目录),然后在flex目录下,放置一个services-config.xml,内容如下:
照抄就好了,不用管太多。基本上这个配置的作用就相当于添加wcf(svc文件)后,系统自动在web.config中增加的配置节点,用于提供一些必要的配置信息.
2.3修改web.config的httpModules节点为以下内容
当然还有一个数据实体类Person.cs
这是用httpwatch在firefox下测试的结果:
如果用最原始的stream方法封装json数据,返回的数据为
如果用系统提供的json自动封装,返回的数据为
而FluorineFx是以二进制返回的,不方便直接观察字符串,只能直接反序列化为Peron类,就不贴出结果了。
从运行图的Received列上可以看出:“FluorineFx返回的数据大小-375” 要小于“wcf默认封装的json数据-389”,但大于“开发者自行处理的json数据大小-312”
再比较Time列,FluorineFx所用的时间是最小的(当然多测试几次,结果稍有不同,但经过我的多次观察,FluorineFx所花的时间始终是最小的)
综合比较下来:FluorineFx传输的数量小,传输时间短,整体效率是不错的,确实是silverlight/.net与其它系统高效传输数据的可选方式之一。
文中所用源代码下载:http://cid-2959920b8267aaca.office.live.com/self.aspx/Silverlight/FluorineFx.rar
1、直接远程加载文本或xml文件 (直接请求ashx/aspx,然后在ashx/aspx上输出信息也可以归入这一类)
2、通过wcf/webService取得数据
(当然,sl跟本机的sl之间也能交换数据,但这个用处有限,此外通过socket也能拿到数据,但是socket要玩好并不容易,难度系数有点高,本文不做讨论)
而返回的数据格式,最常用的通常为"xml"、"json字符串"(或普通字符串) 或 "最原始的Stream"
今天在学习FluorineFx(一个开源的免费项目),并查看它的演示示例时,意外发现FluorineFx也支持silverlight!
与webService采用的soap协议不同:FluorineFx支持Adobe的AMF0,AMF3,RTMP协议,能方便的与Adobe几乎所有的通讯技术交互,这为silverlight与flash/flex交互提供了可能。(详见百度百科FluorineFX http://baike.baidu.com/view/1654458.htm?fr=ala0_1)
下面简单说下silverlight中使用FluorineFx的大概步骤:
基本上 silverlight本身只是一种UI技术,自身并无太强的的数据处理能力(独立存储虽然提供了数据存储和检索能力,但能力实在有限),要获取数据只能借助其它系统或技术,所以我们先把其它系统做好:
1、先用VS.Net(我用的是vs2010)创建一个Library项目,起名为ServiceLib,并在里面创建一个TestLib.cs的类,代码如下:
using System.ComponentModel; using System.Data; using FluorineFx; namespace ServiceLib { [RemotingService] [Description("Test Service")] public class TestLib { [DataTableType("SliverlightApp.Person")] public DataTable GetPersonList() { DataTable tbl = new DataTable(); tbl.Columns.Add("Name", typeof(string)); tbl.Columns.Add("Age", typeof(System.Int32)); tbl.Rows.Add("菩提树下的杨过", 30); tbl.Rows.Add("小龙女", 100); return tbl; } } }
当然,这个项目要引用FluorineFx程序集,该项目的主要用意在于把"取数据"的业务逻辑封装在这一层,以方便重用。
2、再创建一个webApplication,起名为WebApp,同样要添加FluorineFx.dll的引用
2.1 然后创建一个名为Gateway.aspx的文件,这样就行了,不用添加任何多余的代码(这个文件作为调用FluorineFx的网关)
2.2 在根目录下,创建目录Web-INF/flex (即二层目录),然后在flex目录下,放置一个services-config.xml,内容如下:
<?xml version="1.0" encoding="utf-8" ?> <services-config> <services> <service id="remoting-service" class="flex.messaging.services.RemotingService" messageTypes="flex.messaging.messages.RemotingMessage"> <destination id="fluorine"> <channels> <channel ref="my-amf"/> </channels> <properties> <source>*</source> </properties> </destination> </service> </services> <channels> <channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel"> <endpoint uri="http://{server.name}:{server.port}/{context.root}/Gateway.aspx" class="flex.messaging.endpoints.AMFEndpoint"/> <properties> <!-- <legacy-collection>true</legacy-collection> --> </properties> </channel-definition> </channels> </services-config>
照抄就好了,不用管太多。基本上这个配置的作用就相当于添加wcf(svc文件)后,系统自动在web.config中增加的配置节点,用于提供一些必要的配置信息.
2.3修改web.config的httpModules节点为以下内容
2.4 添加对ServiceLib项目的引用 3、最后创建一个silverlight项目,添加FluorineFx.dll引用,命名为SliverlightApp 注意:FluorineFx.dll有二个版本,一个用于webform,一个专用于silverlight(本文最后会给出下载) 通常用vs.net创建一个silverlight项目时,会提示你是否把该项目承载于一个webApplication项目中,以方便测试,这里直接指定第2步中的webApp为承载项目(即相当于webApp项目添加对SliverlightApp的引用) 在silverlight中访问FluorineFx的关键代码如下: using FluorineFx; using FluorineFx.AMF3; using FluorineFx.Messaging.Api.Service; using FluorineFx.Net; ... //点击按钮时,开始调用 private void btnFluorineFx_Click(object sender, RoutedEventArgs e) { NetConnection _netConnection = new NetConnection(); _netConnection.ObjectEncoding = ObjectEncoding.AMF3; _netConnection.NetStatus += new NetStatusHandler(_netConnection_NetStatus); _netConnection.Connect("http://localhost:1718/Gateway.aspx"); _netConnection.Call("ServiceLib.TestLib.GetPersonList", new GetPersonHandler(this)); } //状态回调 private void _netConnection_NetStatus(object sender, NetStatusEventArgs e) { string level = e.Info["level"] as string; this.Dispatcher.BeginInvoke(() => { this.txtResult.Text = "level:" + level + ",code:" + e.Info ["code"] as String; }); } //数据回调处理 private class GetPersonHandler : IPendingServiceCallback { MainPage page; public GetPersonHandler(MainPage page) { this.page = page; } public void ResultReceived(IPendingServiceCall call) { page.Dispatcher.BeginInvoke(() => { page.txtResult.Text = ""; }); object result = call.Result; ArrayCollection items = result as ArrayCollection; foreach (object item in items) { Person p = item as Person;//注意:这里直接将数据反序列化为Person了 page.Dispatcher.BeginInvoke(() => { page.txtResult.Text += p.ToString() + ";"; }); } } }
当然还有一个数据实体类Person.cs
4、最后回过头来,在webApp中把(创建silverlight项目时自动生成的)SliverlightAppTestPage.aspx设置为启动页测试就行了 整个解决方案的目录结构如下: 分析: 传统的soap协议是采用xml格式的,而xml格式的最大问题就是数据太大,比如一个普通的"hello world"字符串,经过xml格式封装后,可能变成<string>hello world</string>,再加上文件头部的xml文档声明,传输数据量最终会增加不少。 为了改进,Adobe发明了AMF0/AMF3协议,AMF是Adobe独家开发出来的通信协议,它采用二进制压缩,序列化、反序列化、传输数据,从而为Flash 播放器与Flash Remoting网关通信提供了一种轻量级的、高效能的通信方式。 所以FluorineFx相对于基于soap协议的web service/wcf而言,应该是效率会更高,不过我们也应该看到微软的进步:wcf在传输数据时,除了xml格式,还可以用json格式甚至直接最原始的stream流格式。为了比较,我在代码中还特意加了test.svc 以json格式返回数据,用于跟fluorinefx做下对比(xml格式就懒得比较了,传输数据量肯定要大于json格式)--test.svc里的具体代码如下: using System.Collections.Generic; using System.Data; using System.IO; using System.ServiceModel; using System.ServiceModel.Activation; using System.ServiceModel.Web; using System.Text; namespace WebApp { [ServiceContract(Namespace = "")] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] public class test { /// <summary> /// 利用系统自动封装成json格式 /// </summary> /// <returns></returns> [OperationContract] [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json)] public List<SliverlightApp.Person> GetPersonList() { List<SliverlightApp.Person> lst = new List<SliverlightApp.Person>(); lst.Add(new SliverlightApp.Person() { Name = "菩提树下的杨过", Age = 30 }); lst.Add(new SliverlightApp.Person() { Name = "小龙女", Age = 100 }); return lst; } /// <summary> /// 自己封装成json格式 /// </summary> /// <returns></returns> [OperationContract] [WebInvoke(Method = "GET")] public Stream GetPersonList2() { DataTable tbl = new DataTable(); tbl.Columns.Add("Name", typeof(string)); tbl.Columns.Add("Age", typeof(System.Int32)); tbl.Rows.Add("菩提树下的杨过", 30); tbl.Rows.Add("小龙女", 100); return GetStream(CreateJsonParameters(tbl)); } /// <summary> /// 将datatable转化成json字符串 /// </summary> /// <param name="dt"></param> /// <returns></returns> private string CreateJsonParameters(DataTable dt) { StringBuilder JsonString = new StringBuilder(); if (dt != null && dt.Rows.Count > 0) { JsonString.Append("{ "); JsonString.Append("\"Head\":[ "); 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("\"", "\\\"") + "\""); } } if (i == dt.Rows.Count - 1) { JsonString.Append("} "); } else { JsonString.Append("}, "); } } JsonString.Append("]}"); return JsonString.ToString(); } else { return null; } } /// <summary> /// 辅助方法,用于输出流 /// </summary> /// <param name="str"></param> /// <returns></returns> private Stream GetStream(string str) { MemoryStream ms = new MemoryStream(); StreamWriter sw = new StreamWriter(ms); sw.AutoFlush = true; sw.Write(str); ms.Position = 0; WebOperationContext.Current.OutgoingResponse.ContentType = "text/plain"; return ms; } } }
这是用httpwatch在firefox下测试的结果:
如果用最原始的stream方法封装json数据,返回的数据为
如果用系统提供的json自动封装,返回的数据为
而FluorineFx是以二进制返回的,不方便直接观察字符串,只能直接反序列化为Peron类,就不贴出结果了。
从运行图的Received列上可以看出:“FluorineFx返回的数据大小-375” 要小于“wcf默认封装的json数据-389”,但大于“开发者自行处理的json数据大小-312”
再比较Time列,FluorineFx所用的时间是最小的(当然多测试几次,结果稍有不同,但经过我的多次观察,FluorineFx所花的时间始终是最小的)
综合比较下来:FluorineFx传输的数量小,传输时间短,整体效率是不错的,确实是silverlight/.net与其它系统高效传输数据的可选方式之一。
文中所用源代码下载:http://cid-2959920b8267aaca.office.live.com/self.aspx/Silverlight/FluorineFx.rar
相关文章推荐
- 转 silverlight获取外部数据的另一种选择:FluorineFx
- easyui datagrid获取选择行的数据
- combox从数据库获取到数据,并且选择的时候得到数据,而不是NULL。
- Silverlight客户端怎样获取外部参数
- C++代码,数据结构-外部排序-置换-选择排序
- abap submit用法(一)调用外部程序(abap内存获取数据)
- 单击gridview控件外部的一个按钮,获取gridview中的一列数据,获得的数据插入到另一个表中
- 获取gridview中选择行时,前一次选择的行的数据
- 算法兴趣----- 一亿数据获取前100个最大值(仅供参考,基于快速排序的实现时间不稳定,基于最小堆实现。如果我们只要求前K个最大(小)值的时候,用堆是最好的选择,因为这里不用每次都排序了)
- select 选择框的下拉数据动态获取
- winform DataGridView 选择行 获取数据
- 使用Socket通信实现Silverlight客户端实时数据的获取(模拟GPS数据,地图实时位置)
- 外部的js文件中获取ASPX页面的数据--解耦初接触
- Excel2010如何获取外部数据比如导入来自网站中的数据
- Silverlight——Silverlight请求HttpHandler获取数据
- C#之DataGridView获取用户选择的行的数据...
- jquery获取radio选择的tr中的数据
- gridview绑定checkbox控件后,通过单击CheckedChanged事件获取当前选择行的数据
- Flash从外部文件(例如cgi)获取数据
- 如何获取jqGrid中选择的行的数据