从 JQuery 调用 WCF 服务:跨域 OPTIONS 请求给出错误 400

Posted

技术标签:

【中文标题】从 JQuery 调用 WCF 服务:跨域 OPTIONS 请求给出错误 400【英文标题】:Call WCF service from JQuery : cross-origin OPTIONS request gives error 400 【发布时间】:2013-09-23 08:04:00 【问题描述】:

我正在尝试从 JQuery 调用 C# WCF SOAP Web 服务

服务托管在 IIS 端口 80 上,客户端从 Apache 端口 81 运行,两者都来自 localhost。所以我陷入了跨域请求。

    使用 Chrome,我得到了预期的结果,但是查看网络流量,它显示 OPTIONS 请求返回错误 400 Bad Request,但是下一个 POST 请求成功:

    使用 Firefox,出现错误(javascript 警报显示 null | error |)。似乎POST 请求未发送,因为OPTIONS 请求失败:

    使用 IE,一切正常,就好像它来自同一个来源......我没有看到任何 OPTIONS 请求:

从接口暴露的功能:

namespace Test

    [ServiceContract]
    public interface IMathService
    
        [OperationContract]
        String HelloWorld();
    

服务配置(Web.config):

<services>
  <service name="Test.MathService" behaviorConfiguration="ServiceBehavior">
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost:80/WCFtest/service.svc" />
      </baseAddresses>
    </host>
    <endpoint address="/soap" binding="basicHttpBinding" contract="Test.IMathService" />
    <endpoint address="/rest" binding="webHttpBinding" contract="Test.IMathService" behaviorConfiguration="WEB" />
  </service>
</services>
[...]
<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="http://localhost:81" />
    <add name="Access-Control-Allow-Headers" value="SOAPAction, Content-type, Accept, Origin" />
    <add name="Access-Control-Allow-Methods" value="POST, GET, PUT, DELETE, OPTIONS" />
  </customHeaders>
</httpProtocol>

JQuery 代码:

$('#btn_helloworld').click(function () 
    var soapRequest = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">' +
                        '<soapenv:Header/>' +
                        '<soapenv:Body>' +
                            '<tem:HelloWorld/>' +
                        '</soapenv:Body>' +
                        '</soapenv:Envelope>';
    $.ajax(
        type: 'POST',
        url: 'http://localhost/WCFtest/service.svc/soap',
        crossDomain: true,
        contentType: 'text/xml',
        dataType: 'xml',
        data: soapRequest,
        beforeSend: function (xhr) 
            xhr.setRequestHeader('SOAPAction', 'http://tempuri.org/IMathService/HelloWorld');
        ,
        success: function (data) 
            $('#outputHelloWorld').val($(data).find('HelloWorldResponse').text());
        ,
        error: function (jqxhr, textStatus, errorThrown) 
            alert(jqxhr.responseXML + ' | ' + textStatus + ' | ' + errorThrown);
        
    );
);

如果从同一来源调用,服务工作正常。

我错过了什么吗?

【问题讨论】:

你有没有得到这个工作? 不,但如果我必须回到问题上并找到解决方案,我肯定会更新我的帖子。 【参考方案1】:

在花了 2 天时间追鬼(浏览器对 CORS 的各种“解释”)之后,我认为结论是:这里的问题是 OPTIONS 请求 - FF 和 Opera 正在发送它,但我不认为IE 可以。另外我不认为 OPTIONS 是 IIS、IIS express 等默认允许的动词。 我在 global.asax 中添加了 Application_BeginRequest:

void Application_BeginRequest(Object sender, EventArgs e)

    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");

    if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
    
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "*");

        HttpContext.Current.Response.End();
    

因此,我设法通过 FF 完成了我的请求。

【讨论】:

以上是关于从 JQuery 调用 WCF 服务:跨域 OPTIONS 请求给出错误 400的主要内容,如果未能解决你的问题,请参考以下文章

如何避免 jquery ajax 中使用 wcf 服务的跨域策略?

跨域 jQuery Ajax 请求和 WCF REST 服务

从 jQuery 访问 Web 服务 - 跨域

WCF 跨域使用 Jsonp 错误未捕获语法错误:意外令牌:

是否可以使用 jQuery 方法 getJSON 跨域将复杂对象传递给 WCF 服务?

跨域调用 WCF 服务