Silverlight中數據訪問的實現方式非常之多,可以直接通過HTTP頁面提供訪問接口,也可以通過WebService、WCF以及其他的相關技術來實現。在MIX
09上,Nikhil Kothari發布了微軟的一神作——Microsoft .NET RIA
Services,主要用來提供RIA應用的數據訪問服務,詳細可以查閱博友 流牛木馬 的《Microsoft
.NET RIA Services快速上手
》這篇文章。在開源項目FluorineFx中也提供了供Silverlight實現RPC的類庫,究竟誰的傳輸效率高呢這里暫不討論,本文作重介紹
如何使用FluorineFx
Silverlight庫去實現Silverlight遠程過程調用(RPC)。
本文實例程序開發環境:Microsoft Visual Studio 2008 +
SP1、.net framework 3.5 + SP1、 Silverlight 3 Beta、FluorineFx v1.0.0.15
。本文最終的項目解決方案如下圖:

一、在Silverlight中的網絡安全訪問限制
如果連接請求是從 WebClient
或 HTTP 類到某個跨域站點的,則 Silverlight 2 運行時將使用 HTTP 協議嘗試下載安全策略文件。Silverlight 2
運行時首先嘗試使用 HTTP 協議下載所請求目標域的根目錄下名為“clientaccesspolicy.xml”的 Silverlight 策略文件。如果返回
Silverlight 策略文件(即使在分析該文件時出現錯誤),則在 Silverlight
應用程序的整個會話期間,此文件將用作該跨域請求以及針對該服務器的所有后續請求的策略文件。如果找不到 Silverlight 策略文件,則 Silverlight
2 運行時嘗試使用 HTTP 協議下載所請求目標域的根目錄下名為“crossdomain.xml”的 Flash 策略。[載自MSDN]
<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<allow-from http-request-headers="*">
<domain uri="*"/>"
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true"/>
</grant-to>
</cross-domain-access>
</access-policy>
二、基與FluorineFx的遠程調用服務接口
接下來創建FluorineFx類庫,提供遠程訪問服務接口(RemotingService),并提供相應的方法讓Sliverlight客戶端通過FluorineFx通信網關實行RPC調用。
namespace ServiceLibrary
{
[RemotingService]
public class DataService
{
public DataService()
{
}
[DataTableType("Book", "ServiceLibrary.Book")]
public DataTable GetBookTable()
{
DataTable dt = new DataTable("Book");
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Author", typeof(string));
dt.Columns.Add("Price", typeof(double));
DataRow dr = dt.NewRow();
dr["ID"] = 1;
dr["Name"] = "《三國演義》";
dr["Author"] = "羅貫中";
dr["Price"] = 100.00;
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["ID"] = 2;
dr["Name"] = "《西游記》";
dr["Author"] = "吳承恩";
dr["Price"] = 200.00;
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["ID"] = 3;
dr["Name"] = "《水滸傳》";
dr["Author"] = "施耐庵";
dr["Price"] = 300.00;
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["ID"] = 4;
dr["Name"] = "《紅樓夢》";
dr["Author"] = "曹雪芹";
dr["Price"] = 400.00;
dt.Rows.Add(dr);
return dt;
}
}
}
三、使用FluorineFx網站宿主FluorineFx遠程服務
供遠程訪問(RemotingService)接口完成后,還需要建立一個FluorineFx網站,用來承載這個接口的遠程服務。并同時配置AMF通信的信道(在services-config.xml中配置)。
<channels>
<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
<endpoint uri="//{server.name}:{server.port}/{context.root}/Gateway.aspx" class="flex.messaging.endpoints.AMFEndpoint"/>
<properties>
</properties>
</channel-definition>
</channels>
然后運行這個網站以得到客戶端RPC訪問時所需要的網關地址,這里是本地測試。如果部署到服務器上則根據實際的部署信息(服務器IP/網站域名等)訪問。本地網關地址://localhost:3103/WebHost/Gateway.aspx。通過FluorineFx控制臺測試便可以看到FluorineFx遠程服務接口方法的調用情況,如下圖示:
四、創建Silverlight應用程序
現在創建一個Silverlight
應用程序,并為此應用程序創建一個宿主這個應用程序客戶端的Web應用程序,這里的宿主Web應用程序就直接創建在上面提供遠程服務接口的FluorineFx網站中,當然你也可以創建新的Web應用程序來宿主Silverlight應用程序客戶端。
五、通過FluorineFx的Silverlight庫實現Silverlight應用的RPC
這里首先定義一個DTO(數據傳輸對象)對象Book,如下:
namespace SilverlightApp
{
public class Book
{
public int ID { get; set; }
public string Name { get; set; }
public string Author { get; set; }
public double Price { get; set; }
public Book()
{ }
}
}
在Siverlight應用中,在舞臺上布局一個按扭,用來發起遠程調用。使用DataGrid控件來顯示調用結果。
<UserControl x:Class="SilverlightApp.MainPage"
xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
xmlns="//schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="//schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Canvas Background="DarkBlue">
<Button Content="RPC調用" Width="80" Height="30"
Canvas.Top="10" Canvas.Left="10"
Background="Blue" Click="Button_Click">
</Button>
<data:DataGrid Canvas.Top="60" Canvas.Left="10" RowHeight="30"
x:Name="bookGrid" AutoGenerateColumns="True">
</data:DataGrid>
</Canvas>
</UserControl>
現在這一步很關鍵,要使Siverlight能夠成功實現RPC,需要使用FluorineFx所提供的Siverlight庫,不是使用FluorineFx
for .NET framework,正確的是使用FluorineFx for
Siverlight庫,此庫位于FluorineFx的安裝目錄x:\FluorineFx\Bin\net\Silverlight2.0\FluorineFx.dll。庫類封裝了Siverlight實現RPC的相關API。
NetConnection nc;
public MainPage()
{
InitializeComponent();
//初始化到FluorineFx網關的連接
nc = new NetConnection();
nc.ObjectEncoding = ObjectEncoding.AMF3;
nc.NetStatus += new NetStatusHandler(onNetStatus);
nc.Connect("//localhost:3103/WebHost/Gateway.aspx");
nc.Client = this;
}
在Siverlight應用程序初始化的時候對遠程訪問連接進行初始化,并為其委托一個網絡連接狀態處理函數onNetStatus。
void onNetStatus(object sender, NetStatusEventArgs e)
{
string code = e.Info["code"] as string;
}
和Flex開發一樣,同樣使用NetConnection的call()方法去調用遠程服務方法,不同的是Siverlight中沒有Resonder去處理方法的返回結果,而是需要自己定義一個回調處理程序去處理返回結果,此處理程序必須實現接口IPendingServiceCallback,詳細如下:
private void Button_Click(object sender, RoutedEventArgs e)
{
nc.Call("ServiceLibrary.DataService.GetBookTable", new RpcResultHandler(this));
}
public void Bind(IList<Book> list)
{
Dispatcher.BeginInvoke(delegate()
{
this.bookGrid.ItemsSource = list;
});
}
namespace SilverlightApp
{
public class RpcResultHandler : IPendingServiceCallback
{
MainPage page;
public RpcResultHandler(MainPage ctl)
{
page = ctl;
}
#region IPendingServiceCallback Members
public void ResultReceived(IPendingServiceCall call)
{
object result = call.Result;
ArrayCollection items = result as ArrayCollection;
IList<Book> list = new List<Book>();
foreach (var item in items)
{
IDictionary<string, object> dic = (((FluorineFx.ASObject)(item))) as IDictionary<string, object>;
string Name = dic["Name"].ToString();
Book book = new Book
{
ID = int.Parse(dic["ID"].ToString()),
Name = dic["Name"].ToString(),
Author = dic["Author"].ToString(),
Price = double.Parse(dic["Price"].ToString())
};
list.Add(book);
}
page.Bind(list);
}
#endregion
}
}
IPendingServiceCallback接口中的ResultReceived()方法專門用來處理RPC調用的結果,這里將返回結果通過相應的解析處理后回調Siverlight應用中的Bind()方法,實現將返回的結果綁定到Siverlight控件DataGrid上。程序運行截圖:

參考文獻://blog.fluorinefx.com/?p=17
本文示例代碼下載:RPCSolution.rar
標簽:
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:博客園