jQuery调用WCF需要注意的一些问题

xlandjQuery调WCF给了我们很大帮助,在这里感谢xland!在探索技术的过程中,将自己解决问题的经验记录下来,不仅可以备忘、总结,而且可以帮助遇到同样问题的朋友,这也是写博客的一种乐趣吧。

进入正题,jQuery调用WCF需要注意的一些问题:

1. WCF的配置(WCF服务宿主于IIS 7)

1)WCF服务相关配置:

在需要调用的接口方法(OperationContract)上加上属性[WebInvoke(RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)],比如:

复制代码

[ServiceContract]
public interface IDiggService
{
[OperationContract]
[WebInvoke(RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
string GetDiggCountList(string entryIdList);
}

复制代码

给服务实现类加上属性:

 [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class DiggService : IDiggService
{
}

否则调用时会出现错误:“IIS 7.0 Detailed Error – 500.0 – System.ServiceModel.ServiceActivationException”。

2) Web.config中的WCF相关配置:

复制代码

<system.serviceModel>
<services>
<service name=”DiggService”>
<endpoint address=”” binding=”webHttpBinding” contract=”IDiggService” behaviorConfiguration=”DiggServiceBehavior”/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name=”DiggServiceBehavior”>
<enableWebScript/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>

复制代码

需要注意两个地方的配置:

a)  binding=”webHttpBinding”,开始设置为binding=”basicHttpBinding”,出现错误提示:

The endpoint at ‘DiggService.svc’ does not have a Binding with the None MessageVersion.  ‘System.ServiceModel.Description.WebScriptEnablingBehavior’ is only intended for use with WebHttpBinding or similar bindings.

b)  <enableWebScript/> ,启用这个设置才能让WCF支持Ajax调用,否则调用时WCF会返回这样的错误:

The message with To ‘DiggService.svc/GetDiggCountList’ cannot be processed at the receiver, due to an AddressFilter mismatch at the EndpointDispatcher. Check that the sender and receiver’s EndpointAddresses agree.

二、客户端jQuery调用注意

开始按照调用Web Servcie的方式调用:

复制代码

$.ajax({
url: ‘/wcf/DiggService.svc/GetDiggCountList’,
data: ‘{“entryIdList”:”‘ + entryIdList + ‘”}’,
type: ‘post’,
dataType: ‘json’,
contentType: ‘application/json; charset=utf8’,
success: function(data) {
if (data.d) {
}
}
},
error: function(xhr) {
alert(xhr.responseText);
}
});

复制代码

在FireFox中能成功调用,但在IE 8和Google Chrome中,调用后返回的却是IIS 7的错误信息:IIS 7.0 Detailed Error – 400.0 – Bad Request。

后来将 contentType: ‘application/json; charset=utf8’ 改为 contentType: ‘text/json’问题就解决了。

jQuery调用Web Service与WCF还有一个不同之处在参数格式的处理上:

比如上面代码中的data: ‘{“entryIdList”:”‘ + entryIdList + ‘”}’,如果将参数名的双引号去掉,即data: ‘{entryIdList:”‘ + entryIdList + ‘”}’,可以正常调用Web Service,调用WCF会出现Json反序列化的异常。

三、其他需要注意的地方

如果WCF服务所在的IIS站点中绑定了多个域名, 在没有设置baseAddressPrefixFilters的情况下,会出现错误提示:

This collection already contains an address with scheme http.  There can be at most one address per scheme in this collection.Parameter name: item

设置好baseAddressPrefixFilters,比如:

    <serviceHostingEnvironment>
<baseAddressPrefixFilters>
<add prefix=”http://www.cnblogs.com”/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>

这样在访问http://www.cnblogs.com时能正常调用,但访问http://cnblogs.com时调用就出错(IIS 7.0 Detailed Error – 404.0 – Not Found),因为之前的代码中使用的是相对地址调用,实际调用的是http://cnblogs.com/wcf/DiggService.svc/GetDiggCountList,由于设置了baseAddressPrefixFilters,不允许这样调用,只能改为绝对地址(http://www.cnblogs.com/wcf/DiggService.svc/GetDiggCountList),这样又会造成跨域调用。这个问题目前还不知如何解决。

四、遗留问题

如何控制缓存,比如:如何在WCF返回时设置Expires Header和If-Modified-Since,避免频繁的WCF调用。

五、总结

jQuery调用WCF的要点:

1. [WebInvoke(RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]

2. [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]

3.  binding=”webHttpBinding”

4. <enableWebScript/>

5.  contentType: ‘text/json’