【问题标题】:WCF 4, JSONP, and jQuery cause parsererrorWCF 4、JSONP 和 jQuery 导致解析器错误
【发布时间】:2012-04-10 14:09:39
【问题描述】:

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

我的 WCF 服务有如下方法:

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

正如Twitter by Patrick Thomas 所述,我也尝试过使用[WebGet(BodyStyle = WebMessageBodyStyle.Wrapped)][WebGet(BodyStyle = WebMessageBodyStyle.WrappedResponse)],但没有成功。

配置如下:

<system.serviceModel>
    <behaviors>
        <serviceBehaviors>
            <behavior>
                <serviceMetadata httpGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
        </serviceBehaviors>
        <endpointBehaviors>
            <behavior name="RestEndpoint">
                <enableWebScript/>
            </behavior>
        </endpointBehaviors>
    </behaviors>
    <bindings>
        <webHttpBinding>
            <binding name="NoSecurityRestBinding" crossDomainScriptAccessEnabled="true">
                <security mode="None" />
            </binding>
        </webHttpBinding>
    </bindings>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    <services>
        <service name="WebServices.TestService">
            <endpoint address="" binding="webHttpBinding" contract="WebServices.ITestService" bindingConfiguration="NoSecurityRestBinding" behaviorConfiguration="RestEndpoint" />
        </service>
    </services>
</system.serviceModel>

该服务位于不同的域中,因此我将数据格式化为 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);
    }
});

我得到:

“解析错误”

“没有调用jQuery16408722478272714725_1332817261195”

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

提前感谢您的帮助!

【问题讨论】:

  • 查看您的服务器响应。它应该类似于:jQuery16408722478272714725_1332817261195({some:json,goes:here});这就是 jQuery 所期待的,但出了点问题。
  • 因此,当我检查服务器响应时,我发现它看起来像是 GET 而不是 POST(尽管客户端和服务器端方法指定 POST)并且 URL 看起来像:@ 987654327@
  • 另外,IE 返回 200,成功但 Chrome 返回 400,错误请求。两者都有带有 jQ​​uery 回调响应的 parsererror。
  • @Jason N. Gaylord 我很确定你需要使用msg 并申请JSON.parse(msg),然后使用msg.TestResult;获取msg的JSON编码数组中TestResult的值。
  • @Ohgodwhy 我已经更新了上面的代码,但仍然遇到同样的问题。

标签: jquery ajax wcf jsonp parse-error


【解决方案1】:

在经历了很多痛苦之后,我设法对一个简单的休息服务进行了简单的 jquery / ajax 调用,并返回带有回调的 jsonp。在尝试在 url 中设置回调后,我终于 设法通过将“jsonpCallback”和回调名称添加到参数来使其工作。

$.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();
}

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

【讨论】:

    【解决方案2】:

    在过去的 3 年里,这个问题已经困扰我好几次了。每次我遇到它并修复它然后忘记做笔记。下次发生这种情况时,我开始抓挠并再次寻找解决方案。所以,让我在这里记录我的解决方案,并与可能处理这个问题的人分享。请按照以下步骤操作,并确保您使用 JQuery 1.8 或更高版本和 .net framework 4.0,它会正常工作。

    • 在system.serviceModel注释下的行为注释中,设置为webHttp:
    <behaviors>
      <endpointBehaviors>
        <behavior name="webHttpBehavior">
          <webHttp />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    
    • 定义一个 JsonP 绑定:
    <bindings>
          <webHttpBinding>
            <binding name="webHttpBindingWithJsonP" crossDomainScriptAccessEnabled="true" />
          </webHttpBinding>
        </bindings>
    
    • 将您的服务 bindingConfiguration 设置为刚刚定义的绑定
    <services>
      <service name="dpRestService.qcmmsService">
        <endpoint address="" behaviorConfiguration="webHttpBehavior"
          binding="webHttpBinding" bindingConfiguration="webHttpBindingWithJsonP"
          contract="gwsRestService.qcmmsService" />
      </service>
    </services>
    
    • 将 Jaon 添加为 ResponseFormat 属性的响应格式

    [WebGet(UriTemplate = "你的服务模板" , ResponseFormat = WebMessageFormat.Json)]

    • jQuery 请求:

    $.ajax({ 网址:网址, type: 'GET', //ajax调用的类型 数据: {}, 内容类型:'应用程序/json', 跨域:是的, 数据类型:'jsonp',
    成功:callBackFun, 错误:errorFun });

    我希望这会有所帮助。

    【讨论】:

      【解决方案3】:

      添加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);
          }
      });
      

      【讨论】:

        【解决方案4】:

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

        如果您还想进行 JSONP 调用并避免解析器错误问题,请使用此类:

        <%@ 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"  %>
        

        【讨论】:

          【解决方案5】:

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

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

          更新

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

          附带说明一下,在 jQuery AJAX 请求上设置 contentType 是没有意义的,因为 JSONP 请求没有正文,因为它都是基于查询字符串的。

          【讨论】:

          • 更新我的答案,提供更多细节,因为我刚刚想起了一些事情。如果我的建议仍然不起作用,请使用最新的代码/配置更新您的问题,以便我们确保我们都在同一页面上。
          【解决方案6】:

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

          【讨论】:

          • 所以我用 GET 更新了两端,我仍然得到相同的响应“parsererror”和“jQuery16408722478272714725_1332817261195 没有被调用”
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-07-06
          • 1970-01-01
          • 2012-07-31
          • 1970-01-01
          相关资源
          最近更新 更多