ios平台调用WCF
最近有个同事在搞一个ios平台的程序,主要是关于OA的。因为windows平台的程序我们现在有现成的服务,所以想直接调用,后台的服务都是wcf服务,因此,首先想到了在ios上用代理的方式访问wcf服务,可惜折腾了好几天,也没弄通,各种尝试。。。gsop工具也试过,总之是代理的方式没搞通。。好了,既然代理不行那就换个思路吧,于是乎,想到了js调用服务的方式,原理应该是一样的,都是通过一个http请求,url的地址上写好方法的名称和需要传递的参数。不过就这样调用wcf服务对于一个初学者来说也是一件充满了各种草泥马的工作啊,有木有。。。
好吧,立马打开谷歌啊,敲上js调用wcf。。案例倒是一堆,按照各位牛人的先例,楼主在自己的项目中配置了一下,我用的是webHttpBinding
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceTypeBehaviors" >
<!-- 将下列元素添加到服务行为配置中。 -->
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webHttpBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="Enjoy.ServicePortal.ServicePortal" >
<endpoint address="" binding="webHttpBinding" behaviorConfiguration="webHttpBehavior"
contract="Enjoy.ServicePortal.IServicePortal" />
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="webHttpBinding0" closeTimeout="10:10:10" openTimeout="10:10:10" receiveTimeout="10:10:10" sendTimeout="10:10:10" maxBufferSize="2147483647"
maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
transferMode="Buffered" useDefaultWebProxy="true">
<readerQuotas maxArrayLength="2147483647" maxStringContentLength="2147483647" maxNameTableCharCount="2147483647"
maxBytesPerRead="2147483647" maxDepth="640" />
</binding>
</webHttpBinding>
</bindings>
</system.serviceModel>
折腾了半天,wcf真的好复杂,绑定的方式就一堆。。。测试了下,好像只有webHttpBinding这种方式才支持url后面加上方法名直接调用wcf方法,不知道说的对不对,请高手指点下。。不过我测试的结果是这样的。
好了,配置文件调好了,wcf的契约中的方法我们也要修改下,在方法名称的上面加上如下属性:
[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Xml,ResponseFormat = WebMessageFormat.Xml, Method = "POST")]
string getByteData(XElement bt);
通过url 的方式调用wcf服务数据的传输无非是两种方式,json/xml,这里RequestFormat用的是xml格式的数据,如果采用了xml格式的数据的话,也就意味着http请求过来的数据一定要能反序列化成xml格式的数据,否则会报400请求错误。ok,这些属性加上之后就可以调用我们的服务了,ios那边的客户端传过来一个xml格式的字符串<DataModel><VALUE>hello wcf,我是ios客户端!</VALUE></DataModel>,这样的数据,经过wcf处理是没有问题的,当比特流在网络上传输到服务端的时候,wcf会自动将http请求中的数据反序列化成一个XElement对象。因此服务的参数必须要是一个xelement对象,然后从这个对象中取到自己想用的参数;
好了,上面的方法调用wcf服务没有问题了,已经调通了,因为我们这里是调用一个服务的门面,由这个服务的门面再去决定调用那些后台的服务,所以说这里是一个服务的接入点。ok,需求又来了,因为是移动平台上的项目,所以对网络负载的要求也是比较高的。所以增加了压缩和解压的步骤,就是客户端在调用服务的时候要先将数据压缩,以达到减少网络负载的目的。好了,客户端还是刚刚的那些数据,这段xml数据经过压缩之后通过比特流直接传到服务端,但是结果总是报400的错误,提示是一个错误的请求,不压缩正常,压缩之后就出现了400的错误,很明显是压缩的之后的数据传到服务端之后,wcf在进行反序列化的时候没有反序列化成一个xml对象,原因是数据经过压缩之后那些byte数据已经改变了,后来想到一个办法,就是手工包装压缩后的数据,我们是这样做的:数据还是要压缩,压缩完之后对这些字节再进行base64加密成文本类型的base64编码,然后外面再用<Data></Data>将加工好的数据包装起来,这样就可以直接调用服务端的方法。