WCF 4,JSONP和jQuery导致parsererror

我已经尝试了几乎所有我能想到的东西,但是我仍然遇到了对我的ajax调用WCF服务的问题。

我的WCF服务有如下方法:

//[WebInvoke(ResponseFormat = WebMessageFormat.Json, Method = "POST")] [WebGet] public string Test(int value) { return string.Format("You entered: {0}", value); } 

正如Patrick Thomas在Twitter上所提到的,我也尝试过使用[WebGet(BodyStyle = WebMessageBodyStyle.Wrapped)][WebGet(BodyStyle = WebMessageBodyStyle.WrappedResponse)]而没有运气。

和配置如下:

                             

该服务位于不同的域,所以我将我的数据格式化为JSONP:

 $.ajax({ cache: false, async: true, type: "GET", // Was "POST" dataType: "jsonp", url: "http://mydomain.com/TestService.svc/Test?callback=?", data: dataToPost, contentType: "application/json;charset=utf-8", success: function (msg) { var testMsg = JSON.parse(msg); var status = testMsg.TestResult; alert(status); }, error: function (msg) { alert('Please email Jason with this exception: ' + msg.statusText); } }); 

我得到了:

“parsererror”

“jQuery16408722478272714725_1332817261195未被调用”

我可能做错了什么? 我确实validation了所有WCF二进制文件都是4.0。

在此先感谢您的帮助!

您不希望将enableWebScript行为应用于端点。 这特别支持Microsoft的ASP.NET AJAX客户端堆栈,该堆栈具有针对所有请求/响应的特定JSON编码。 用webHttp替换它,看看是否能解决你的问题。 其他一切看起来都不错。

我建议的下一件事是将webHttp行为元素的automaticFormatSelection属性设置为true。 这样,当检测到HTTP请求的接受内容类型为JSON时,它将确保将响应序列化为JSON。

更新

我记得的是,由于这是JSONP,请求将来自标记,因此WCF可能默认为XML响应。 因此,您希望在webHttp行为上设置defaultOutgoingResponseFormat ="Json" ,以便默认情况下使用JSON格式化响应。

作为旁注,在jQuery AJAX请求上设置contentType是没有意义的,因为JSONP请求没有主体,因为它基于所有查询字符串。

如果您想避免WCF web.config麻烦,那么您可以将“Factory”属性添加到您的WCF标记。

如果您还想进行JSONP调用并避免出现parsererror问题,请使用此类:

 <%@ ServiceHost Language="C#" Service="MyWebApp.MyWCFService" Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory" %> 

使用以下类覆盖工厂

 using System.Collections.Generic; using System.Linq; using System.Web; using System.ServiceModel.Activation; using System.ServiceModel; using System.ServiceModel.Web; using System.ServiceModel.Description; public class JSONPEnabledWebServiceHostFactory : ServiceHostFactory { protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) { return new JSONPEnabledWebServiceHost(serviceType, baseAddresses); } private class JSONPEnabledWebServiceHost : WebServiceHost { public JSONPEnabledWebServiceHost(Type serviceType, Uri[] baseAddresses) : base(serviceType, baseAddresses) { } protected override void OnOpening() { base.OnOpening(); foreach (ServiceEndpoint endpoint in this.Description.Endpoints) { WebHttpBinding webBinding = endpoint.Binding as WebHttpBinding; if (webBinding != null) { webBinding.CrossDomainScriptAccessEnabled = true; } } } } } 

所以现在你的工厂属性将是

 <%@ ServiceHost Language="C#" Service="MyWebApp.MyWCFService" Factory="MyWebApp.JSONPEnabledWebServiceHostFactory" %> 

JSONP和跨域调用不支持POST请求。 JSONP返回由填充(回调函数)包装的JSON片段。 在后面,它被处理为页面DOM中动态添加的script元素,指向跨域地址。 加载目标脚本资源后,将执行回调函数。 因此,您只能使用GET请求 – script元素无法执行POST。

添加jsonpCallback选项

 $.ajax({ jsonpCallback: 'yourCallbackFunctionName', cache: false, async: true, type: "GET", // Was "POST" dataType: "jsonp", url: "http://mydomain.com/TestService.svc/Test?callback=?", data: dataToPost, contentType: "application/json;charset=utf-8", success: function (msg) { var testMsg = JSON.parse(msg); var status = testMsg.TestResult; alert(status); }, error: function (msg) { alert('Please email Jason with this exception: ' + msg.statusText); } }); 

在过去的3年里,这个问题已经被我多次窃听过了。 每次我遇到它并修好它然后忘了记笔记。 下次它发生时,我开始抓挠并再次寻找解决方案。 所以,让我在这里记录我的解决方案,并与可能处理这个问题的人分享。 按照以下步骤确保您使用的是JQuery 1.8或更高版本的.net framework 4.0,它将起作用。

  • 在system.serviceModel注释下的行为记录中,设置为webHttp:
        
  • 定义JsonP绑定:
      
  • 将您的服务bindingConfiguration设置为刚刚定义的绑定
      
  • 添加Jaon作为ResponseFormat属性的响应格式

[WebGet(UriTemplate =“ 您的服务模板 ”,ResponseFormat = WebMessageFormat.Json)]

  • Jquery请求:

$ .ajax({url:url,type:’GET’,// ajax调用数据的类型:{},contentType:’application / json’,crossDomain:true,dataType:’jsonp’,
成功:callBackFun,错误:errorFun});

我希望这将有所帮助。

经过很多痛苦,我设法得到一个简单的jquery / ajax调用一个简单的rest服务返回jsonp与回调。 在尝试在url中设置回调后,我终于设法通过将“jsonpCallback”和回调名称添加到params来使其工作。

 $.ajax({ type : 'GET', url : 'http://localhost:8080/RestimpleApp/report/extract', dataType : 'jsonp', jsonpCallback : "jsoncallback", success : function(json) { alert('success'); }, error : function(jqXHR, status) { alert("Failed " + status + jqXHR); } }); 

在服务器端,我不得不将我的响应JSON包装在回调名称中(“jsoncallback”)。

 @GET @Produces({ MediaType.APPLICATION_JSON }) public String extractData() { System.out.println("Incoming call = "); StringBuilder json = new StringBuilder("jsoncallback("); json.append("{\"sEcho\": 7,"); json.append("\"iTotalRecords\": \"600\","); json.append("\"iTotalDisplayRecords\": \"12\","); json.append("\"aaData\": ["); json.append("{"); json.append("\"engine\": \"Gecko\","); json.append("\"browser\": \"Firefox 1.0\","); json.append("\"platform\": \"Win 98+ / OSX.2+\","); json.append("\"version\": \"1.7\","); json.append("\"grade\": \"A\""); json.append("},"); json.append("{"); json.append("\"engine\": \"Gecko\","); json.append("\"browser\": \"Firefox 1.5\","); json.append("\"platform\": \"Win 98+ / OSX.2+\","); json.append("\"version\": \"1.8\","); json.append("\"grade\": \"A\""); json.append("} ]"); json.append("}"); json.append(");"); return json.toString(); } 

浪费了很多时间试图让这个工作:(