2

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

我的 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)]但没有成功。

和这样的配置:

<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。

在此先感谢您的帮助!

4

6 回答 6

2

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

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

更新

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

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

于 2012-03-27T15:18:46.800 回答
2

如果您想避免 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"  %>
于 2012-09-28T09:02:38.320 回答
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({ url: url, type: 'GET', //ajax调用类型 data: {}, contentType: 'application/json', crossDomain: true, dataType: 'jsonp',
success: callBackFun, error:错误Fun });

我希望这将有所帮助。

于 2013-12-11T00:04:38.710 回答
1

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

于 2012-03-27T08:42:37.020 回答
1

添加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);
    }
});
于 2013-01-26T08:40:34.287 回答
-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();
}

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

于 2014-03-26T05:00:33.590 回答