【问题标题】:Post JSON ajax request with cors not working in IE10/Edge在 IE10/Edge 中使用 cors 发布 JSON ajax 请求
【发布时间】:2016-11-21 22:45:48
【问题描述】:

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

测试:- 当我尝试执行跨域 ajax 调用时,它在 IE10/Edge 中适用于 GET 请求和 POST 请求(仅那些不接受数据作为 json 的 post 方法)。我可以在 chrome/Firebox 浏览器中对任何 GET/POST 请求进行跨域调用。只有在 ajax 调用中传递 contenttype:accept/json 参数时,IE 10/Edge 会导致跨域调用 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 的 BeginRequest 事件中编写了代码来处理 Options 请求:-

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

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

请专家帮助我!

【问题讨论】:

  • 将dataType更改为“jsonp”是否允许请求?
  • 我试过了,它允许请求但是错误的请求错误。
  • 您是否尝试过 api fetch 而不是 $.ajax ? Fetch 是新的标准。 todojs.com/…

标签: jquery ajax wcf cors iis-7.5


【解决方案1】:

您可以在客户端检查几件事:

  • 您正试图覆盖$.support.cors。这是(或曾经)是一个可读的属性,告诉您浏览器是否支持 CORS。 (请参阅 jQuery source 了解检查的位置)
  • 基于jQuery docs for ajax,您可能希望将xhrFields: { withCredentials: true } 添加到$.ajax() 选项中
  • 使用dataType: "json"charset=UTF-8的正确大小写

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

重要提示:在响应凭据请求时,服务器必须指定域,并且不能使用通配符。如果标头被通配符为:Access-Control-Allow-Origin: *.

,上面的示例将失败

【讨论】:

  • 我删除了 $.support.cors,因为它已经是真的,更正了数据类型和字符集的语法。并将 Access-Control-Allow-Origin 设置为特定于我调用服务的 domian。但是还是不行。
  • 你能分享你用来设置 Access-Control-Allow-Origin 的代码吗?只是为了确认它在飞行前和实际请求中的存在,以及检查它的内容(或者回显Origin,或硬编码以包含正确的 http://https:// 协议。)我还想知道如果您使用像 test-cors.org 这样的服务,您是否在 IE10 / Edge 中看到任何问题?
  • 我应该如何分享代码?我的意思是你的任何 id 我可以分享你吗?
  • 我建议编辑/更新问题中的代码(如果您需要审查主机名,只需使用 'example.com',但重要的是不要更改语法 - 即 @987654337 @ 将变为 http://example.com/,而不是 http://example.comhttps://example.com/ 或普通的 example.com
  • 我更新了从 fiddler 获取的请求和响应标头。
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-27
    • 2018-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-24
    • 2014-12-08
    相关资源
    最近更新 更多