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(); }
浪费了很多时间试图让这个工作:(