昨天,部落格園首頁增加了Digg功能。在該功能中我們開始嘗試使用jQuery直接調用WCF。之前我們采用的方案是jQuery調用Web Service,然後WebService再調用服務層。這樣調用主要是因為之前需要調用不同域名下的WCF服務,因為跨域調用的問題,就要通過Web Service中轉一下。而這次Digg功能調用的是同一個應用程式下的WCF,用jQuery直接調用WCF是更好的選擇。在嘗試這種方式的過程中遇到的一些問題和一些需要注意的地方需要記錄一下,是以就寫了這篇随筆。
進入正題,jQuery調用WCF需要注意的一些問題:
1. WCF的配置(WCF服務宿主于IIS 7)
1)WCF服務相關配置:
在需要調用的接口方法(OperationContract)上加上屬性[WebInvoke(RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)],比如:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuQWZzUTOhljM0cTO2ATOwATNxMWM1EWYxEjY5ADNlFTNfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.gif)
[ServiceContract]
public interface IDiggService
{
[OperationContract]
[WebInvoke(RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
string GetDiggCountList(string entryIdList);
}
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuQWZzUTOhljM0cTO2ATOwATNxMWM1EWYxEjY5ADNlFTNfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.gif)
給服務實作類加上屬性:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class DiggService : IDiggService
{
}
否則調用時會出現錯誤:“IIS 7.0 Detailed Error - 500.0 - System.ServiceModel.ServiceActivationException”。
2) Web.config中的WCF相關配置:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuQWZzUTOhljM0cTO2ATOwATNxMWM1EWYxEjY5ADNlFTNfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.gif)
<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>
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuQWZzUTOhljM0cTO2ATOwATNxMWM1EWYxEjY5ADNlFTNfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.gif)
需要注意兩個地方的配置:
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.
c) 當出現 如下錯誤
使用“UriTemplate”的終結點無法用于“System.ServiceModel.Description.WebScriptEnablingBehavior”。
把 <enableWebScript/>換成<webHttp/>,解決!
二、用戶端jQuery調用注意
開始按照調用Web Servcie的方式調用:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuQWZzUTOhljM0cTO2ATOwATNxMWM1EWYxEjY5ADNlFTNfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.gif)
$.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);
}
});
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuQWZzUTOhljM0cTO2ATOwATNxMWM1EWYxEjY5ADNlFTNfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.gif)
在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'
參考文章:
轉自:http://www.cnblogs.com/dudu/archive/2009/07/14/1523082.html
參考:http://www.cnblogs.com/yjmyzz/archive/2009/11/04/1595783.html