在前一篇文章《.Net Compact Framework 3.5对Linq的支持》中,主要介绍了对Linq的一些使用,这篇文章将介绍另一大.Net CF3.5的新特性--对WCF的支持。
随着微软WCF的逐步推广,越来越多的系统都将会采用WCF作为数据交互,如果在移动设备上还单纯的保留原先的对Web Service的支持,将使得企业不得不面临保留原先Web Service接口,再开发基于WCF的接口,保留2套,多费事。现在都采用WCF之后,企业只需要将原先基于Web Service升级到WCF即可。省事~~。
废话不多说了,开始介绍如何在.Net CF3.5中使用WCF吧。
开发环境:VS2008+Windows Mobile 5.0 PPC
首先创建一个空的Web Site,然后添加一个WCFService文件,VS2008会自动创建一个IService.cs和Service.cs,修改这2个文件,来定义OperationContract及DataContract。具体如何开发WCF,文章最后会有推荐文章。
在WCF中,将实现2个功能,一个测试功能(传入2个int数,返回2数相加),另一个返回一个List泛型数组,存放数据。最初写该Demo时,我返回的是DataTable类型,但DataTable类型并不是WCF所建议使用的。稍后会有说明。
WCF写完后,就需要对web.config进行设置。我用的是WCF Configuration工具,在web.config文件右键,Open With中可以添加该工具。通过该工具可以很方便的配置完一个WCF。
启动后效果如下:
接着开发客户端,创建一个WM5.0的一个工程,选择.Net CF3.5。在界面上放置一个DataGrid,将WCF传来的数组绑定到该DataGrid中。客户端比较简单,关键在调用WCF的地方。
在调用WCF之前,通过使用SvcUtil.exe来生成出所需要的Client端调用代码(.NET Compact Framework Power Toys 3.5)。该程序在Program File\Microsoft.Net\SDK\Compact Framework\v3.5\bin下。
通过键入:netcfSvcUtil.exe /language:cs http://localhost:3721/WCFSite/Service.svc 来解析生成客户端的调用文件。会生成2个文件,一个叫CFClientBase.cs,另一个是你Service的cs文件。
将这2个文件添加到工程中,然后在调用WCF的地方,创建ChannelBinding、Endpoint和ServiceClient对象,然后调用WCF方法即可。
代码如下:
Code
1 System.ServiceModel.Channels.Binding binding = ServiceClient.CreateDefaultBinding();
2 string remoteAddress = ServiceClient.EndpointAddress.Uri.ToString();
3
4 // Server IP Address
5 remoteAddress = remoteAddress.Replace("localhost", "10.16.172.204");
6 EndpointAddress endpoint = new EndpointAddress(remoteAddress);
7 ServiceClient client = new ServiceClient(binding, endpoint);
8 try
9 {
10 //MessageBox.Show(client.Add(10, 20).ToString());
11 this.dataGrid1.DataSource = client.GetUserInfo();
12 }
13 catch (Exception ex)
14 {
15 MessageBox.Show(ex.Message);
16 }因为我的WCF在本地,所以需要将其中remoteAddress需要替换成WCF所在的Service地址。
代码完成后开始进行测试,点击Get Data,返回数据,效果如下:
发现数据排列不是我想要的,这时候就需要改变DataMember中的Attribute,设置其Order顺序。效果如下:
工程如下:
Tips:
1。在实际测试中,因为公司网络设置代理服务器,所以,需要将模拟设备中的代理去除,并不允许连接到Internet,才能进行访问WCF,否则会需要用户验证。
2。WCF不返回DataSet和DataTable的理由:
DataSet和DataTable类型是可序列化的,因而我们可以在服务契约中接收或返回数据表或数据集。
如果服务契约使用了DataSet和DataTable类型,生成的代理文件不会直接使用DataSet和DataTable类型,而是包含DataTable数据契约的定义(只包含DataTable的样式,而不包含任何代码)。但我们可以手工修改这些定义。
注意,DataRow类型是不能序列化的。
在WCF中,还可以使用DataTable和DataSet的类型安全的子类。书中也给出了相应的例子。然而,WCF的最佳实践则是避免使用DataTable和DataSet,以及使用DataTable和DataSet的类型安全的子类。在《Programming WCFServices》书中阐释了原因:
“对于WCF的客户端与服务而言,虽然可以通过ADO.NET和VisualStudio工具使用DataSet、DataTable以及它们的类型安全的派生对象,但这种方式过于繁琐。而且,这些数据访问类型都是特定的.NET类型。在序列化时,它们生成的数据契约样式过于复杂,很难与其它平台进行交互。在服务契约中使用数据表或者数据集还存在一个缺陷,那就是它可能暴露内部的数据结构。同时,将来对数据库样式的修改会影响到客户端。虽然在应用程序内部可以传递数据表,但如果是跨越应用程序或公有的服务边界发送数据表,却并非一个好的主意。通常情况下,更好的做法是暴露数据的操作而非数据本身。”
3。WCF可以不创建Web Site方式,可以创建Host方式来打开关闭WCF。这里不做说明。