原文 www.cyqdata.com/cnblogs/article-detail-39983-english

越来越多的朋友都在使用Silverlight开发应用程序,其中我们常用的还会有一个特殊的服务,就是RIA Service,具体来说,它是一个所谓的Domain Service. 关于这个服务的基本概念,如果有不清楚,请参考下面这个网址

http://www.silverlight.net/getstarted/riaservices/

今天这一篇是要谈谈一个问题,就是如何让RIA Service支持WPF此类客户端来访问?

你可能会疑惑,这难道是一个问题吗?是的,RIA Service默认只能在Silverlight里面访问到。我们还是通过一个例子来讲解一下吧

1. 定义一个业务实体类

namespace WebApplication1
{
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
using System.ServiceModel.DomainServices.Server; [DataContract]
public class Employee
{
[Key][DataMember]
public int ID { get { return this.GetHashCode(); } } [DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
}
}

2. 创建一个Domain Service

namespace WebApplication1
{
using System.Linq;
using System.ServiceModel.DomainServices.Hosting;
using System.ServiceModel.DomainServices.Server; // TODO: Create methods containing your application logic.
[EnableClientAccess()]
public class SampleDomainService : DomainService
{
[Query]
public IQueryable<Employee> GetEmployees()
{
return new[]{
new Employee{FirstName="ares",LastName="chen"},
new Employee{FirstName="mike",LastName="fei"},
new Employee{FirstName="tom",LastName="jerry"}
}.AsQueryable();
}
}
}

【备注】需要注意的是,Domain Service是没有svc文件的,这与标准的WCF服务是完全不同的。

RIA Service 的 SOAP EndPoint-LMLPHP

3. 在Silverlight应用程序中访问这个服务

作为演示,我们做了一个很简单的界面

<UserControl x:Class="SilverlightApplication1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"> <Grid x:Name="LayoutRoot" Background="White">
<sdk:DataGrid AutoGenerateColumns="True" Margin="24,53,21,25" Name="dataGrid1" />
<TextBlock Height="33" HorizontalAlignment="Left" Margin="25,14,0,0" Name="textBlock1" Text="Employee List" VerticalAlignment="Top" Width="219" FontSize="25" />
</Grid>
</UserControl>

然后通过如下的代码调用数据

using System.Windows;
using System.Windows.Controls; namespace SilverlightApplication1
{ using WebApplication1; public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent(); Loaded += new RoutedEventHandler(MainPage_Loaded);
} void MainPage_Loaded(object sender, RoutedEventArgs e)
{
var ctx = new SampleDomainContext();
var op = ctx.Load<Employee>(ctx.GetEmployeesQuery());
dataGrid1.ItemsSource = op.Entities;
}
}
}

从上面的代码不难看出,在Silverlight调用RIA Service的时候,是相当容易的,这里不用指定路径,也无需有其他更多设置。

得到的页面效果如下

RIA Service 的 SOAP EndPoint-LMLPHP

你可能会有一个疑问,那么到底是调用了什么服务呢?

我们通过IE 9自带的开发工具,可以监控一下得到一个特殊的WCF地址

RIA Service 的 SOAP EndPoint-LMLPHP

最后一行,很明显是一个WCF的调用地址,我们很好奇的是,它到底传递了什么东西过来呢?

RIA Service 的 SOAP EndPoint-LMLPHP

该服务返回的其实是一个二进制的包,具体内容如下

RIA Service 的 SOAP EndPoint-LMLPHP

虽然不能完全看懂,但可以确定的是,这是二进制序列化的结果。

那好,我们回到刚才的话题,既然这是一个WCF服务,而且也确实有一个隐含的svc地址(注意,我说的是隐含,因为物理上并不存在该文件),那么是否可以通过该地址,发起普通的服务调用呢?

我们尝试将http://localhost:11547/ClientBin/WebApplication1-SampleDomainService.svc 这个地址输入到浏览器地址栏

RIA Service 的 SOAP EndPoint-LMLPHP

令人欣喜的是,我们看到了熟悉的WCF WSDL的界面。

那么,这是否意味着,我们可以在除了Silverlight之外的其他应用程序中调用该服务呢?

4. 创建WPF应用程序,添加服务引用

很不幸的是,我们在WPF中尝试添加服务引用时,却会遇到下面的错误

RIA Service 的 SOAP EndPoint-LMLPHP

详细的错误如下,意思是说,没有找到有关的endpoint.

RIA Service 的 SOAP EndPoint-LMLPHP

5. 安装RIA Service Toolkit以便添加SOAP EndPoint支持

为了解决如上的问题,微软在4月份发布了一个Toolkit,可以为RIA Service添加SOAP EndPoint支持

请先通过下面的地址下载

http://www.microsoft.com/download/en/details.aspx?id=2384

具体来说,这个工具包提供了很多增强的功能

安装好之后,我们会得到一些Assembly,在如下的目录

C:\Program Files (x86)\Microsoft SDKs\RIA Services\v1.0\Toolkit\Libraries\Server

本例中,我们将使用其中一个Microsoft.ServiceModel.DomainServices.Hosting.dll 来提供SOAP EndPoint支持,所以我们要将其添加到Web项目的引用列表中来

RIA Service 的 SOAP EndPoint-LMLPHP

6. 修改Web.config,添加SOAP EndPoint

熟悉WCF的朋友都知道,WCF是基于配置的,无处不在的配置使得服务很灵活并且强大。本例中,我们也只需要修改配置文件,就可以完成添加SOAP EndPoint的工作。下面的粗体部分是我们添加的

    <system.serviceModel>
<domainServices>
<endpoints>
<add name="OData" type="System.ServiceModel.DomainServices.Hosting.ODataEndpointFactory, System.ServiceModel.DomainServices.Hosting.OData, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add name="Soap" type="Microsoft.ServiceModel.DomainServices.Hosting.SoapXmlEndpointFactory,
Microsoft.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />

</endpoints>
</domainServices>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
</system.serviceModel>
 
 

保存配置文件,我们再去浏览器中访问该服务。你有没有发现有什么不同呢?如果有,请告诉我吧

RIA Service 的 SOAP EndPoint-LMLPHP

7. 在WPF中完成服务引用,并且使用它发起调用

RIA Service 的 SOAP EndPoint-LMLPHP

是的,你没有看错,我们找到了这个服务。

好吧,既然能够添加引用,接下来的事情你应该会做了吧?当然,不是很难,你懂的

MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid AutoGenerateColumns="True" Margin="12,62,12,12" Name="dataGrid1" />
<TextBlock Height="33" HorizontalAlignment="Left" Margin="12,23,0,0" Name="textBlock1" Text="Employee List" FontSize="25" VerticalAlignment="Top" Width="224" />
</Grid>
</Window>

MainWindow.xaml.cs

using System.Windows;

namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent(); Loaded += new RoutedEventHandler(MainWindow_Loaded);
} void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
var proxy = new RIA.SampleDomainServiceSoapClient();
dataGrid1.ItemsSource = proxy.GetEmployees().RootResults;
}
}
}

RIA Service 的 SOAP EndPoint-LMLPHP

BTW:我觉得WPF的界面(例如这个DataGrid)看起来没有Silverlight那么好看,不是吗? 当然,这个话题还是等我们以后有机会再来谈谈吧

总结

RIA Service默认只能被Silverlight访问,它确实极其方便。如果希望它能被其他客户代码访问到,则可以通过安装RIA Service Toolkit,为其添加SOAP Endpoint来实现。

04-29 04:21