Ответ на предполетный период имеет недопустимый код статуса HTTP 405

Я прочитал много подобных проблем в StackOverflow, но решения для меня не работают.

У меня есть служба 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": ""
      })  

Я только что скопировал URL и JSON из Postman. Но я получаю сообщение об ошибке:

angular.js: 10722 ВАРИАНТЫ http://192.168.1.65/Service1.svc/restapi/PostItem http://192.168.1.65/Service1.svc/restapi/PostItem. Ответ для preflight имеет недопустимый код статуса HTTP 405

Я искал похожие проблемы и нашел два решения:

  • Используйте jQuery для установки заголовка Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', но он не работает с моей службой WCF
  • Установите собственные заголовки в моем 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 может успешно вызвать этот метод.

Как я могу сделать тот же POST-вызов, используя AngularJS?

Обновление

Вот запрос OPTIONS:

введите описание изображения здесь

Вкладки просмотра и ответа пустые

Обновление 2:

Все работает отлично в IE, но не работает в Chrome.

Ответ 1

Похоже, я нашел решение. Я просто добавил второй метод:

[<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

Это просто пустые методы, которые ничего не делают. Я не знаю причины, но все работает.

Ответ 2

Я хочу показать, что работа для меня.

Сначала вы должны включить CORS на 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>

Если у вас есть дополнительный параметр 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();
    }
}

Ответ 3

Хотя у этого уже есть ответ, но это мое решение. В веб-конфигурации вы должны удалить инструкцию до <remove name="OPTIONSVerbHandler" />

Сначала добавьте в 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 Team опубликовала модуль IIS CORS, взломам как пустые методы больше не нужны. Он имеет дело с CORS, включая предполетные запросы. Вы можете настроить его в веб-конфигурации, например:

<?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

Я только что решил ту же проблему с удалением xhr.setRequestHeader() в моем запросе AJAX. Если у кого-то есть код, попробуйте удалить его.

Ответ 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 (класс приложения Global) и добавьте следующий код:

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