发布带有 cors 的 JSON ajax 请求在 IE10/Edge 中不起作用

Post JSON ajax request with cors not working in IE10/Edge

提问人:ateet 提问时间:7/19/2016 最后编辑:ateet 更新时间:1/6/2020 访问量:4690

问:

背景:-我创建了一个托管在本地系统 IIS 中的 WCF 服务。服务公开了 GET/POST 方法并启用了跨域,也可以使用 https 进行访问。为了使其可访问,使用了自签名证书。

测试:-当我尝试进行跨域ajax调用时,它在IE10 / Edge中对GET请求和POST请求(仅那些不接受数据作为json的post方法)工作正常。我能够在 chrome/Firebox 浏览器中对任何 GET/POST 请求进行跨域调用。只有IE 10 / Edge在ajax调用中传递contenttype:accept/json参数时导致对POST请求进行跨域调用的问题。

研究:-我阅读了很多博客/mdn,并了解了 IE 不虔诚地遵循 cors 的 cors 规范。我知道 cors 规范不会分配自定义标头/标头的值,因此 cors 预检中止。

我提出的ajax请求示例:-

var postDT = { "postValue": "test" };
        debugger;
        $.support.cors = true;
        $.ajax({
            type: "POST",
            data: JSON.stringify(postDT),
            url: "http://ateet3371/Service1.svc/postdata",
            contentType: "application/json; charset=utf-8",
            dataType: "JSON",
            processData: true,
            success: function (data) {
                 alert(data);
            },
            error: function (jqXHR, textStatus, errorThrown) {
                var a = jqXHR;
                alert(jqXHR + '---' + textStatus + '---' + errorThrown);
            }
        });

如果我删除了,那么它会抛出错误的请求错误,否则它会抛出拒绝访问错误。contentType: "application/json; charset=utf-8"

WCF 中的方法实现是:-

[OperationContract]
    [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, UriTemplate = "PostResponseData")]
    string PostResponseData(PostDataTest postDT);

数据合同是:-

[DataContract]
public class PostDataTest
{
    private string post_value;

    // Apply the DataMemberAttribute to the property.
    [DataMember]
    public string postValue
    {

        get { return post_value; }
        set { post_value = value; }
    }
}

如果我使用方法 PostUrl 数据,则 ajax 调用将成功执行,如果从请求中删除 ContentType:“Application/json” 标头,则返回正确的结果。

[OperationContract]
    [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "PostUrlData/{value}")]
    string PostUrlData(string value);

我已经在WCF的Global.asax的StartRequest事件中编写代码来处理选项请求:-

HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
        if (HttpContext.Current.Request.HttpMethod == "OPTIONS" )
        { 
        //These headers are handling the "pre-flight" OPTIONS call sent by the browser
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, HEAD");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Origin, Content-Type, Accept, X-Requested-With, Session");
        HttpContext.Current.Response.AddHeader("Access-Control-Expose-Headers", "DAV, content-length, Allow" );
        HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000" );
        HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache,no-store");
        HttpContext.Current.Response.End();
        } 

我无法在IE中启用设置,因为最终用户不会执行此类步骤。Allow cross domain call

卡在问题中:-但仍然无法在 IE 10/Edge(已启用 cors)中执行 JSON 数据后调用。

(已编辑)更新:承载 WCF 的 IIS 站点仅启用匿名身份验证,而禁用其他身份验证即使我尝试使用有效的 https 证书,但它仍然不适用于 IE,但非常适合 chrome。

请求标头

OPTIONS https://service.domian.com/projectservice.svc/GetMultiListData HTTP/1.1 Accept: */* Origin: https://sitename.servicedomain.com Access-Control-Request-Method: POST Access-Control-Request-Headers: content-type, accept Accept-Encoding: gzip, deflate User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko Host: sitename.servicedomain.com Content-Length: 0 Connection: Keep-Alive Cache-Control: no-cache

响应标头

HTTP/1.1 200 OK Cache-Control: no-cache,no-store Server: Microsoft-IIS/7.5 Access-Control-Allow-Origin: sitename.servicedomain.com Access-Control-Allow-Methods: GET,POST,PUT,HEAD Access-Control-Allow-Credentials: true Access-Control-Allow-Headers: Origin,Content-Type,Accept,X-Requested-With,Session Access-Control-Expose-Headers: DAV,content-length,Allow Access-Control-Max-Age: 1728000 X-Powered-By: ASP.NET Date: Thu, 04 Aug 2016 17:26:27 GMT Content-Length: 0

请帮助我,因为我浏览了很多文章和博客,但仍然无法解决问题。 您的帮助将不胜感激!

专家请帮帮我!

jQuery ajax WCF CORS IIS-7.5

评论

0赞 Jake Bown 7/29/2016
将 dataType 更改为“jsonp”是否允许请求?
0赞 toto 7/17/2020
您是否尝试过 api fetch 而不是 $.ajax ?Fetch 是新的标准。todojs.com/......

答:

0赞 searlea 8/3/2016 #1

您可以在客户端检查以下几点:

  • 您正在尝试覆盖 .这是(或曾经)是一个可读的属性,告诉您浏览器是否支持 CORS。(有关检查位置,请参阅 jQuery 源代码$.support.cors
  • 根据 ajax 的 jQuery 文档,您可能希望添加到选项中xhrFields: { withCredentials: true }$.ajax()
  • 使用 和 的正确大小写dataType: "json"charset=UTF-8

在服务器端,您可能希望尝试使用特定的主机名(回显标头)而不是响应标头中的通配符 () 进行响应。这在 MDN 中特别提到,在讨论 Access-Control-Allow-Credentials 的段落中:Origin*Access-Control-Allow-Origin

重要说明:在响应凭据请求时,服务器必须指定域,并且不能使用通配符。如果标头通配符为:Access-Control-Allow-Origin: *,则上述示例将失败。

评论

0赞 ateet 8/3/2016
我删除了 $.support.cors,因为它已经是真的,更正了数据类型和字符集的语法。并将 Access-Control-Allow-Origin 设置为特定于 domian 的 domian,从我调用服务的地方。但它仍然不起作用。
0赞 searlea 8/3/2016
您能否分享您用于设置 Access-Control-Allow-Origin 的代码 - 只是为了确认它在预检和实际请求中的存在,以及检查其内容(回显或硬编码以包含正确的 vs 协议。我还想知道,如果您使用像 test-cors.org 这样的服务,您是否在 IE10 / Edge 中看到任何问题?Originhttp://https://
0赞 ateet 8/4/2016
我应该如何与您分享代码?我的意思是你的任何 ID,我可以分享你吗?
0赞 searlea 8/5/2016
我建议编辑/更新问题中的代码(如果您需要审查主机名,只需使用“example.com”,但重要的是不要更改语法 - 即 会变成 、 不是 或 普通 。http://www.google.com/http://example.com/http://example.comhttps://example.com/example.com
0赞 ateet 8/5/2016
我更新了从 fiddler 获取的请求和响应标头。
0赞 HARDCODE Studios 1/6/2020 #2

这不是一个长期的解决方案,但您可以查看 https://cors-anywhere.herokuapp.com/ 您可以通过此毫无问题地获取甚至 POST 数据。 在 URL 之前包含他们的链接,以便 https://cors-anywhere.herokuapp.com/http://ateet3371/Service1.svc/postdata 并将其设置为ajax中的URL值。就像我说的,这不是一个长期的解决方案,但如果它有效,那么看看你能从那里做些什么。

我希望我能提供更多帮助。祝你好运!