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

时间:2013-09-18 14:01:42

标签: jquery wcf web-services soap cross-domain

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

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

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

  2. 使用Firefox时会出现错误(JavaScript警报显示null | error |)。似乎POST请求未发送,因为OPTIONS请求失败: enter image description here

  3. 使用IE,一切正常,好像来自同一个来源......我没有看到任何OPTIONS请求: enter image description here

  4. 界面中的公开函数:

    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 个答案:

答案 0 :(得分:8)

花了两天时间追逐幽灵(浏览器对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获得了我的请求。