Wince设备使用WCF BasicHttpBinding方式与平台交互
最近公司要将后台系统移植部分功能到PDA设备上,于是开始研究手持终端设备,目前大部分工业级别手持设备均采用WINCE系统。
第一个需要解决的问题就是如何与系统交互。因为我们原系统客户端是WINFORM,交互方式是采用WCF wsHttpBinding方式。研究了一下发现微软为Mobile设备准备的NET Compact Framework 3.5使用比较局限,无法使用原来的那种信道绑定方式。
目前.NET CF3.5预定义的仅支持BasicHttpBinding和WindowsMobileMailBinding两种方式:
1) BasicHttpBinding,从本质上来讲,基本和原来调用Web Service的方式一样,因为它支持在http下进行传统的C/S互操作,客户端只需发出一个服务请求并等待回应。
2) WindowsMobileMailBinding,这是一个Compact WCF中全新的通信方式,它使用Email作为消息传输的载体,提供了一个全双工的通讯信道,允许进行非可靠的双向异步通信。
本文就介绍一下第一种方式的实现。(摘自http://www.cnblogs.com/fox23/archive/2008/03/28/wmadv5.html)
WCF服务器端可以有多种方式运行:控制台、IIS WebService、或者用WINFORM界面控制都可以,本文采用IIS WebService方式。
首先创建一个WebApplication,添加一个类,命名为你的service.svc,修改其中代码为
<%@ ServiceHost Language="C#" Service="WCFDemo.DeviceSvc"%>
修改webConfig 添加如下节点:
<system.serviceModel>
<!--Basic Binding-->
<services>
<service behaviorConfiguration="basicBindingServiceBehavior" name="CP.Service.Inventory.DeviceSvc">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IDataService" contract="WCFDemo.IDeviceSvc"/>
<!--<endpoint address="mex" binding="basicHttpBinding" name="mexEndpoint" contract="IMetadataExchange"/>-->
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="basicBindingServiceBehavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true" />
<CPCustomErrorHandler/>
<serviceThrottling
maxConcurrentCalls="10000"
maxConcurrentSessions="10000"
maxConcurrentInstances="10000" />
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior>
<dataContractSerializer
maxItemsInObjectGraph="2147483647" />
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="CPCustomErrorHandler" type="CP.Interface.ErrorHandlerElement, CP.Interface" />
</behaviorExtensions>
</extensions>
<protocolMapping>
<add binding="basicHttpBinding" scheme ="http"/>
</protocolMapping>
<!-- 以下参数设置WCF服务器连接的一些属性 -->
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IDataService"
maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647"
maxBufferSize="2147483647"
openTimeout="00:01:00"
closeTimeout="00:01:00"
receiveTimeout="00:05:00"
sendTimeout="00:05:00">
<readerQuotas maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxDepth="2147483647"
maxNameTableCharCount="2147483647" maxStringContentLength="2147483647"/>
</binding>
</basicHttpBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
这些属性页可以用代码显示赋值的方式:
XMLSerialHelper xmlSerialHelper = new XMLSerialHelper(typeof(TransmittedObject));
//按BasicHttpBinding的方式构建传输信道
BasicHttpBinding binding = new BasicHttpBinding();
BindingParameterCollection parameters = new BindingParameterCollection();
IChannelListener<IReplyChannel> listener =
binding.BuildChannelListener<IReplyChannel>(new Uri("http://localhost:10008"), parameters);
//启用Channel Listener
listener.Open();
创建接口 WCFDemo.IDeviceSvc
// 注意: 如果更改此处的接口名称“IService1”,也必须更新 App.config 中对“IService1”的引用。
[ServiceContract]
public interface IDeviceSvc
{
[OperationContract]
string GetString(int value);
[OperationContract]
CompositeType GetDataUsingDataContract(CompositeType composite);
}
实现接口
/ 注意: 如果更改此处的类名“IService1”,也必须更新 App.config 中对“IService1”的引用。
public class WcfDemoService : IWcfDemoService
{
public string GetString(int value)
{
// TODO:参照此方法,传递和返回标准数据类型
return "Hello World";
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
// TODO:参照此方法,定义自己的 CompositeType, 传递和返回自定义数据类型
if (composite.BoolValue)
{
composite.StringValue = String.Format("Service replys at {0} when you say '{1}'",
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), composite.StringValue);
}
return composite;
}
}
其中使用到的自定义类型类:
// 使用下面示例中说明的数据协定将复合类型添加到服务操作
[DataContract]
public class CompositeType
{
bool boolValue = true;
string stringValue = "Hello ";
[DataMember]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
[DataMember]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
服务器工作基本完成,发布IIS,设置端口,然后可以测试一下是否可以浏览成功,发布成功之后可以看到如下页面
然后可使用Power Toys的NetCFSvcUtil.exe工具生成客户端代理类。
在Command下
cd C:\Program Files\Microsoft.NET\SDK\CompactFramework\v3.5\bin
netcfsvcutil.exe /language:cs http://youraddress/CP.WCFServer.Device/DeviceSvc.svc
之后可见生成的2个文件
这2个文件中就包含接口方法的调用,CompositeType通用类型的定义。
客户端可以创建一个静态方法用来返回对于服务器的调用
public static DeviceSvcClient GetSvc()
{
System.ServiceModel.Channels.Binding bind = DeviceSvcClient.CreateDefaultBinding();
string remoteAddress = DeviceSvcClient.EndpointAddress.Uri.ToString();
EndpointAddress endpoint = new EndpointAddress(remoteAddress);
DeviceSvcClient client = new DeviceSvcClient(bind, endpoint);
return client;
}
调用代码
public static string GetString()
{
return GetSvc().GetStriing();
}
然后创建一个SmartDeviceProject,模板选择DeviceApplication,创建一个新窗体,添加按钮,按钮事件调用Messbox.Show( ServiceHelper.Getstring);
成功获取Service端发来的"HelloWorld"。
至此Compact Framework于平台系统通讯成功。
Framework