asmx web 服务 - jQuery ajax post json (500 错误) - CORS (Access-Control-Allow-Origin 设置为 *)

Posted

技术标签:

【中文标题】asmx web 服务 - jQuery ajax post json (500 错误) - CORS (Access-Control-Allow-Origin 设置为 *)【英文标题】:asmx web service - jQuery ajax post json (500 error) - CORS (Access-Control-Allow-Origin is set to *) 【发布时间】:2012-09-20 15:19:37 【问题描述】:

这个主题似乎是一个拥有一百万个“解决方案”的主题,结果更加复杂。所以请放慢我的脚步,因为我将尝试展示发生了什么,我正在使用什么以及我是如何尝试解决这个问题的。

我的测试环境是IIS6 asp.net 2.0,我已经设置好了

'Access-Control-Allow-Origin' *

我还将 .asmx 扩​​展的动词设置为

"GET,HEAD,POST,DEBUG,OPTIONS"

通过 jQuery v1.7.2 ajax() 调用,我能够从服务器获取 xml 文件,并将 POST 发送到返回具有跨域预期结果的字符串的基本服务。所以我知道我的跨域请求至少部分有效。

当我开始扩展它并使用 json 将数据发布到服务时,我的问题就出现了

我有一个简单的 asmx webservice 方法:

        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public SubResponse HelloWorldX(SubRequestXX SubReq)
        
            SubResponse sr = new SubResponse();

            sr.resultCode = "777";
            sr.resultMsg = "hello - " + SubReq.EmailAddress;

            return sr;
        

非常简单,并没有什么神奇的地方发生,我要做的就是传递“SubRequestXX”对象,现在只需验证它到达那里并做出响应。

Using jQuery:

    $.ajax(
        type: "POST",
        url: "http://somedomain/subscription/MyService.asmx/HelloWorldX",
        processData: false,
        data: ' "SubReq" : "EmailAddress":"user@test.com" ',
        dataType: "json",
        contentType: "application/json; charset=utf-8",
        cache: false,
        success: function(data, textStatus, jqXHR) 
            ajaxSucccess3(data, textStatus, jqXHR);
        ,
        error: function(jqXHR, textStatus, errorThrown) 
            console.log("Retrieve Hello Failed (AJAX Error): " + jqXHR.statusText + " | " + textStatus + " | " + errorThrown);
        
    );

也许答案就在那里?但这是 fiddler 的 RAW 数据显示我使用来自同一域上的页面的完全相同的 JS 代码(成功 - 结果代码 200):

REQUEST:
    POST http://somedomain/subscription/Service.asmx/HelloWorldX HTTP/1.1
    Accept: application/json, text/javascript, */*; q=0.01
    Content-Type: application/json; charset=utf-8
    X-Requested-With: XMLHttpRequest
    Referer: http://somedomain/subscription/subscription_-cors.html
    Accept-Language: en-us
    Accept-Encoding: gzip, deflate
    User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; 9LA)
    Host: somedomain
    Content-Length: 45
    Connection: Keep-Alive
    Pragma: no-cache

     "SubReq" : "EmailAddress":"user@test.ca" 

RESPONSE:

    HTTP/1.1 200 OK
    Date: Fri, 28 Sep 2012 16:59:15 GMT
    Server: Microsoft-IIS/6.0
    X-Powered-By: ASP.NET
    Access-Control-Allow-Origin: *
    X-AspNet-Version: 2.0.50727
    Cache-Control: private, max-age=0
    Content-Type: application/json; charset=utf-8
    Content-Length: 147

    "d":"__type":"SubService.DataObj.SubResponse","resultCode":"777","resultMsg":"hello - rob@test.ca"

所以一切看起来都很好,并且表现如预期。现在,如果我采用相同的 html/js 代码,部署在另一台服务器上并发出相同的请求(跨站点)提琴手显示(失败结果代码 500):

REQUEST:
    POST http://somedomain/subscription/Service.asmx/HelloWorldX HTTP/1.1
    Accept: */*
    Origin: http://www.crossdomainsite.com
    Accept-Language: en-US
    Accept-Encoding: gzip, deflate
    User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; 9LA)
    Host: somedomain
    Content-Length: 0
    Connection: Keep-Alive
    Pragma: no-cache


RESPONSE:
HTTP/1.1 500 Internal Server Error
Date: Fri, 28 Sep 2012 16:58:56 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Access-Control-Allow-Origin: *
X-AspNet-Version: 2.0.50727
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 4732

.....

Request format is unrecognized for URL unexpectedly ending in '/HelloWorldX'

.....

[InvalidOperationException: Request format is unrecognized for URL unexpectedly ending in '/HelloWorldX'.]
   System.Web.Services.Protocols.WebServiceHandlerFactory.CoreGetHandler(Type type, HttpContext context, HttpRequest request, HttpResponse response) +405961
   System.Web.Services.Protocols.WebServiceHandlerFactory.GetHandler(HttpContext context, String verb, String url, String filePath) +212
   System.Web.Script.Services.ScriptHandlerFactory.GetHandler(HttpContext context, String requestType, String url, String pathTranslated) +47
   System.Web.HttpApplication.MapHttpHandler(HttpContext context, String requestType, VirtualPath path, String pathTranslated, Boolean useAppConfig) +193
   System.Web.MapHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +93
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

许多搜索结果表明对 web.config 进行了一些更改。如果我将以下内容添加到我的 system.web 部分:

    <webServices>
        <protocols>
            <add name="HttpGet"/>
            <add name="HttpPost"/>
        </protocols>
    </webServices>

那么我的请求看起来像

POST http://somedomain/subscription/Service.asmx/HelloWorldX HTTP/1.1
Accept: */*
Origin: http://www.crossdomainsite.ca
Accept-Language: en-US
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; 9LA)
Host: somedomain
Content-Length: 0
Connection: Keep-Alive
Pragma: no-cache

我的回应:

HTTP/1.1 500 Internal Server Error
Date: Fri, 28 Sep 2012 17:37:00 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Access-Control-Allow-Origin: *
X-AspNet-Version: 2.0.50727
Cache-Control: private
Content-Type: text/plain; charset=utf-8
Content-Length: 461

System.InvalidOperationException: HelloWorldX Web Service method name is not valid.
   at System.Web.Services.Protocols.HttpServerProtocol.Initialize()
   at System.Web.Services.Protocols.ServerProtocol.SetContext(Type type, HttpContext context, HttpRequest request, HttpResponse response)
   at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest request, HttpResponse response, Boolean& abortProcessing)

因此,将该部分添加到我的 web.config 中有所作为,因为我的结果略有不同。但我无法辨别是什么。

其他解决方案建议使用这些 web 配置设置,因为我使用的是 asp.net 2.0,请注意,我在上述所有结果中都保留了这些设置,注释掉的是来自项目创建的原件:

        <httpHandlers>
            <remove verb="*" path="*.asmx"/>
            <!--<add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>-->
            <add path="*.asmx" verb="*" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />

            <!--<add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>-->
            <add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

            <!--<add verb="GET,HEAD" path="ScriptResource.axd" validate="false" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>-->
            <add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/>
        </httpHandlers>

所以... 一个大问题... 为什么我的跨站点请求失败并使用相同的代码,尽管上述所有内容?似乎只要请求来自另一个域,它就会阻塞 JSON。

任何帮助将不胜感激解决这个谜。我假设它要么是 IIS6(服务器)设置,要么是我的 $.ajax() 调用,我觉得它可能很简单或很小,但我似乎无法确定它。

【问题讨论】:

【参考方案1】:

我通过 JSONP 尝试了类似的东西。我想我的解决方案基于这篇文章。

JSONP + CORS

另一个潜在的事情是,将 JSON 作为字符串放入 WCF 服务通常不会很好地结束(我知道这不是 WCF,只是说它可能是同一个问题)。我通常这样做:

Using jQuery:

$.ajax(
    type: "POST",
    url: "http://somedomain/subscription/MyService.asmx/HelloWorldX",
    processData: false,
    data: JSON.parse(' "SubReq" : "EmailAddress":"user@test.com" '),
    dataType: "json",
    contentType: "application/json; charset=utf-8",
    cache: false,
    success: function(data, textStatus, jqXHR) 
        ajaxSucccess3(data, textStatus, jqXHR);
    ,
    error: function(jqXHR, textStatus, errorThrown) 
        console.log("Retrieve Hello Failed (AJAX Error): " + jqXHR.statusText + " | " + textStatus + " | " + errorThrown);
    
);

使用 JSON.parse 也会捕获任何通过的错误 JSON。

希望这能解决您的问题。

【讨论】:

以上是关于asmx web 服务 - jQuery ajax post json (500 错误) - CORS (Access-Control-Allow-Origin 设置为 *)的主要内容,如果未能解决你的问题,请参考以下文章

jQuery Ajax 到 asp.net asmx web 服务抛出请求格式无效:application/json

asmx 接受 ajax post,jQuery ajax request from asmx web service

甩掉 ashx/asmx,使用jQuery.ajaxWebService请求WebMethod,Ajax处理更加简练

jQuery AJAX POST 到 ASMX Web 服务导致“无法将 System.String 类型的对象转换为 System.Collections.Generic.IDictionary”

asmx web 服务 - jQuery ajax post json (500 错误) - CORS (Access-Control-Allow-Origin 设置为 *)

如何从 2.0 asmx Web 服务返回 JSON