【问题标题】:Response for preflight has invalid HTTP status code 405预检响应具有无效的 HTTP 状态代码 405
【发布时间】:2026-01-04 23:05:02
【问题描述】:

我在 * 中阅读了许多类似的问题,但这些解决方案对我不起作用。

我有 WCF REST 服务:

[<OperationContract>]    
    [<WebInvoke(UriTemplate = "PostItem", 
            RequestFormat= WebMessageFormat.Json,   
            ResponseFormat = WebMessageFormat.Json, Method = "POST")>]         

我可以使用 Postman(Chrome 扩展程序)来使用它。我将数据作为“原始”而不是“urlencoded”传递。我得到 200 返回码。

我需要使用 angularjs 调用这个方法:

    $http.post('http://192.168.1.65/Service1.svc/restapi/PostItem',                   
                {
    "Address": "г. Москва, ул. Соколово-Мещерская, д.25",
     ...
    "User": ""
      })  

我刚刚从 Postman 复制了 URL 和 JSON。但我得到了错误:

angular.js:10722 选项 http://192.168.1.65/Service1.svc/restapi/PostItem http://192.168.1.65/Service1.svc/restapi/PostItem。回应 预检具有无效的 HTTP 状态代码 405

我搜索了类似的问题,找到了两种解决方案:

  1. 使用 jQuery 设置标题 Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',但它不适用于我的 WCF 服务
  2. 在我的 Web.Config 中设置自定义标头:

    <httpProtocol>
       <customHeaders>
          <add name="Access-Control-Allow-Origin" value="*" />
          <add name="Access-Control-Allow-Headers" value="Content-Type" />
          <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
       </customHeaders>
    </httpProtocol>
    

这对我没有帮助。而且我不确定服务器端错误的原因。 Postman 扩展可以成功调用该方法。

如何使用 AngularJS 进行相同的 POST 调用?

更新

这是 OPTIONS 请求:

评论和回复标签为空

更新 2:

在 IE 中一切正常,但在 Chrome 中不起作用。

【问题讨论】:

  • 通常 .Net 会发送错误信息及其 405 状态码...你收到了吗?
  • 我已更新我的问题并在 Chrome 中添加此请求的屏幕。
  • 否,请查看您发布的更新图片,查看“预览”选项卡
  • 预览和响应标签为空
  • 尝试将我们的 WCF 函数中的所有参数设置为可选。让我知道这是做什么的

标签: javascript angularjs wcf rest


【解决方案1】:

我想展示什么对我有用。

首先,您必须在web.config启用 CORS(就像 Mihai 伤心):

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Headers" value="Content-Type" />
    <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE,     OPTIONS" />
  </customHeaders>
</httpProtocol>

如果您有一些额外的 HEADER 参数,则必须将其添加到 Access-Control-Allow-Headers,例如:

<add name="Access-Control-Allow-Headers" value="Content-Type, X-Your-Extra-Header-Key" />

最后,要处理 OPTIONS 请求,您必须回复空响应,并在您的应用程序类中添加:

protected void Application_BeginRequest()
{
    if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
    {
        Response.Flush();
    }
}

【讨论】:

  • 我在 ASP net web api 4 中遇到了同样的错误。请建议怎么办
  • 我有时会在某些 dll 文件损坏时得到它。你有没有办法测试服务器是否返回了一些东西?它发生在您拨打的每个电话中,还是仅在某些情况下发生?
  • 简单的 $.ajax 调用工作正常,但是当从 $http(angularjs 模块)发出请求时,它给出了这个错误。我已经发布了一个问题:*.com/questions/37629422/…
  • 冲洗对我有用(相应地赞成)但我不明白为什么。如果没有这个,我的 JQuery Ajax 调用可以正常工作,当在移动设备上但在 VisualStudio 中运行时,我从同一个 JQuery 调用中得到 405。冲洗到底有什么作用?为什么需要它?
【解决方案2】:

看起来我找到了解决方案。我刚刚添加了第二种方法:

[<OperationContract>]    
[<WebInvoke(UriTemplate = "PostTest", 
        RequestFormat= WebMessageFormat.Json,   
        ResponseFormat = WebMessageFormat.Json, Method = "POST")>]         
abstract PostTest: obj: Test -> unit

[<OperationContract>]    
[<WebInvoke(UriTemplate = "PostTest", 
        RequestFormat= WebMessageFormat.Json,   
        ResponseFormat = WebMessageFormat.Json, Method = "OPTIONS")>]         
abstract PostTestOptions: unit -> unit

这只是什么都不做的空方法。我不知道原因,但一切正常。

【讨论】:

  • 之所以有效,是因为您的 web.config 中已经有 customHeaders 可以返回 COR 期望的内容,但是您没有允许 OPTIONS 的 uriTemplate。所以,在你创建了一个 emtpy 方法之后,预检就可以工作了,它从 customHeaders 中得到了预期的标头。
  • 这可行,但我认为您可以将现有方法更改为 Method = "OPTIONS" 而无需复制它。它仍然会发布数据。
  • 非常感谢。这对我有用,多年来一直在挠头。请参阅我的帖子*.com/questions/48449208/… 我只尝试了 Method=OPTIONS 并且失败了
【解决方案3】:

虽然这已经有了答案,但这是我的解决方案。 在网络配置中,您必须删除对&lt;remove name="OPTIONSVerbHandler" /&gt; 的指令

首先在customHeaders中添加

<httpProtocol>
  <!-- THESE HEADERS ARE IMPORTANT TO WORK WITH CORS -->
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Methods" value="POST, PUT, DELETE, GET, OPTIONS" />
    <add name="Access-Control-Allow-Headers" value="content-Type, accept, origin, X-Requested-With, X-Authentication, name" />
  </customHeaders>
</httpProtocol>

然后要么注释掉要么删除指令来移除OPTIONSverbHandler

<handlers>
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <!-- <remove name="OPTIONSVerbHandler" /> -->
  <remove name="TRACEVerbHandler" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>

【讨论】:

    【解决方案4】:

    自从 IIS 团队发布 IIS CORS module 以来,不再需要像空方法这样的黑客攻击。它正确处理 CORS,包括预检请求。您可以在 web config 中进行配置,例如:

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
        <system.webServer>
            <cors enabled="true" failUnlistedOrigins="true">
                <add origin="*" />
                <add origin="https://*.microsoft.com"
                     allowCredentials="true"
                     maxAge="120"> 
                    <allowHeaders allowAllRequestedHeaders="true">
                        <add header="header1" />
                        <add header="header2" />
                    </allowHeaders>
                    <allowMethods>
                         <add method="DELETE" />
                    </allowMethods>
                    <exposeHeaders>
                        <add header="header1" />
                        <add header="header2" />
                    </exposeHeaders>
                </add>
                <add origin="http://*" allowed="false" />
            </cors>
        </system.webServer>
    </configuration>
    

    【讨论】:

      【解决方案5】:

      我刚刚通过在我的 AJAX 请求中删除 xhr.setRequestHeader() 解决了同样的问题。如果有人在代码中有一个,请尝试将其删除。

      【讨论】:

        【解决方案6】:

        对我有用的解决方案:

        1. 将此添加到 web.config(服务器端):

           <httpProtocol>
            <customHeaders>
              <add name="Access-Control-Allow-Origin" value="*" />
              <add name="Access-Control-Allow-Headers" value="Content-Type" />
              <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE,  OPTIONS" />
            </customHeaders>
          </httpProtocol>
          
        2. 创建一个Global.asax文件(全局应用类)并添加如下代码:

              protected void Application_BeginRequest(object sender, EventArgs e){
                  if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
                      {
                          Response.Flush();
                      }
              }
          

        【讨论】:

        • 这是一个可行的解决方案,没有必要仅仅因为它看起来不太好而对其投反对票。