Как поддерживать HTTP OPTIONS-глагол в приложении ASP.NET MVC / WebAPI

Я установил веб-приложение ASP.NET, начиная с шаблона MVC 4 / Web API. Кажется, что все работает очень хорошо – никаких проблем, о которых я знаю. Я использовал Chrome и Firefox, чтобы пройти через сайт. Я тестировал Fiddler, и все ответы, похоже, были на деньги.

Итак, теперь я приступаю к написанию простого Test.aspx для использования этого нового веб-API. Соответствующие части скрипта:

 $(function () { $.ajax({ url: "http://mywebapidomain.com/api/user", type: "GET", contentType: "json", success: function (data) { $.each(data, function (index, item) { .... }); } ); }, failure: function (result) { alert(result.d); }, error: function (XMLHttpRequest, textStatus, errorThrown) { alert("An error occurred, please try again. " + textStatus); } }); });  

Это генерирует заголовок REQUEST:

 OPTIONS http://host.mywebapidomain.com/api/user HTTP/1.1 Host: host.mywebapidomain.com User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Firefox/24.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Origin: http://mywebapidomain.com Access-Control-Request-Method: GET Access-Control-Request-Headers: content-type Connection: keep-alive 

Как и в случае с API Web API, метод 405 не допускается.

 HTTP/1.1 405 Method Not Allowed Cache-Control: no-cache Pragma: no-cache Content-Type: application/xml; charset=utf-8 Expires: -1 Server: Microsoft-IIS/8.0 X-AspNet-Version: 4.0.30319 X-Powered-By: ASP.NET Date: Mon, 30 Sep 2013 13:28:12 GMT Content-Length: 96 The requested resource does not support http method 'OPTIONS'. 

Я понимаю, что глагол OPTIONS по умолчанию не подключен в controllerах Web API … Итак, я поместил следующий код в свой UserController.cs:

 // OPTIONS http-verb handler public HttpResponseMessage OptionsUser() { var response = new HttpResponseMessage(); response.StatusCode = HttpStatusCode.OK; return response; } 

… и это устранило ошибку 405 Method Not Allowed, но ответ полностью пуст – данные не возвращаются:

 HTTP/1.1 200 OK Cache-Control: no-cache Pragma: no-cache Expires: -1 Server: Microsoft-IIS/8.0 X-AspNet-Version: 4.0.30319 X-Powered-By: ASP.NET Date: Mon, 30 Sep 2013 12:56:21 GMT Content-Length: 0 

Должна быть дополнительная логика … Я не знаю, как правильно закодировать метод «Параметры», или если controller даже подходит для размещения кода. Странно (мне), что сайт веб-API правильно реагирует при просмотре с Firefox или Chrome, но ошибка .ajax выше ошибок. Как я могу обработать проверку «предполетного» кода .ajax? Может быть, я должен решить эту проблему на логике .ajax на стороне клиента? Или, если это проблема на стороне сервера из-за отсутствия обработки глагола OPTIONS.

Может ли кто-нибудь помочь? Это должно быть очень распространенной проблемой, и я приношу свои извинения, если на это был дан ответ. Я искал, но не нашел ответов, которые помогли.

ОБНОВЛЕНИЕ ИМХО, это проблема с клиентской стороной и связана с кодом Ajax JQuery выше. Я говорю это, потому что Fiddler не показывает никаких заголовков ошибок 405, когда я обращаюсь к mywebapidomain / api / user из веб-браузера. Единственное место, где я могу дублировать эту проблему, – это вызов JQuery .ajax (). Кроме того, идентичный вызов Ajax выше работает нормально при запуске на сервере (тот же домен).

Я нашел другое сообщение: запрос прототипа AJAX отправляется как ОПЦИИ, а не GET; приводит к ошибке 501, которая, по-видимому, связана, но я не без труда справлялся с их предложениями. По-видимому, JQuery закодирован таким образом, что если запрос Ajax является кросс-доменом (это мой), он добавляет пару заголовков, которые каким-то образом запускают заголовок OPTIONS.

 'X-Requested-With': 'XMLHttpRequest', 'X-Prototype-Version': Prototype.Version, 

Просто кажется, что должно быть лучшее решение, доступное, чем изменение кода ядра в JQuery …

В приведенном ниже ответе предполагается, что это проблема на стороне сервера. Возможно, я думаю, но я склоняюсь к клиенту, и вызов хостинг-провайдера не поможет.

Как отметил в своем комментарии Daniel A. White, запрос OPTIONS скорее всего создается клиентом как часть запроса JavaScript для перекрестного домена. Это делается автоматически с помощью совместимых браузеров Cross Origin Resource Sharing (CORS). Запрос представляет собой предварительный или предполетный запрос, сделанный до фактического запроса AJAX, чтобы определить, какие глаголы запроса и заголовки поддерживаются для CORS. Сервер может выбрать поддержку для него, ни для одного, ни для некоторых HTTP-глаголов.

Для завершения изображения запрос AJAX содержит дополнительный заголовок «Origin», в котором указано, откуда была загружена исходная страница, на которой размещается JavaScript. Сервер может выбрать поддержку запроса из любого источника или только для набора известных, надежных источников. Разрешение любого происхождения является угрозой безопасности, поскольку может увеличить риск получения запроса на перекрестный сайт (CSRF).

Итак, вам нужно включить CORS.

Вот ссылка, которая объясняет, как это сделать в ASP.Net Web API

http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api#enable-cors

Описанная там реализация позволяет указать, среди прочего,

  • Поддержка CORS на основе действия, для каждого controllerа или глобальной базы
  • Поддерживаемые источники
  • При включении controllerа CORS или глобального уровня поддерживаемые HTTP-глаголы
  • Поддерживает ли сервер отправку учетных данных с запросами на кросс-начало

В целом, это работает отлично, но вы должны убедиться, что знаете о рисках безопасности, особенно если вы разрешаете запросы на кросс-поиск из любого домена. Подумайте очень внимательно, прежде чем разрешить это.

В терминах, которые браузеры поддерживают CORS, Wikipedia говорит, что следующие двигатели поддерживают это:

  • Gecko 1.9.1 (FireFox 3.5)
  • WebKit (Safari 4, Chrome 3)
  • MSHTML / Trident 6 (IE10) с частичной поддержкой в ​​IE8 и 9
  • Престо (Опера 12)

http://en.wikipedia.org/wiki/Cross-origin_resource_sharing#Browser_support

Ответ Майка Гудвина велик, но казалось, когда я попробовал, он был нацелен на MVC5 / WebApi 2.1. Зависимости для Microsoft.AspNet.WebApi.Cors не очень понравились моему проекту MVC4.

Самый простой способ включить CORS в WebApi с MVC4 был следующим.

Обратите внимание, что я разрешил все, я предлагаю вам ограничить Origin только теми клиентами, которым вы хотите, чтобы ваш API работал. Разрешить все риски для безопасности.

Web.config:

          

BaseApiController.cs:

Мы делаем это, чтобы разрешить HTTP-глаголы OPTIONS

  public class BaseApiController : ApiController { public HttpResponseMessage Options() { return new HttpResponseMessage { StatusCode = HttpStatusCode.OK }; } } 

Просто добавьте это в свой метод Application_OnBeginRequest (это позволит поддерживать CORS во всем мире для вашего приложения) и «обрабатывать» предполетные запросы:

 var res = HttpContext.Current.Response; var req = HttpContext.Current.Request; res.AppendHeader("Access-Control-Allow-Origin", req.Headers["Origin"]); res.AppendHeader("Access-Control-Allow-Credentials", "true"); res.AppendHeader("Access-Control-Allow-Headers", "Content-Type, X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Date, X-Api-Version, X-File-Name"); res.AppendHeader("Access-Control-Allow-Methods", "POST,GET,PUT,PATCH,DELETE,OPTIONS"); // ==== Respond to the OPTIONS verb ===== if (req.HttpMethod == "OPTIONS") { res.StatusCode = 200; res.End(); } 

* security: имейте в виду, что это позволит отправлять запросы ajax из любого места на ваш сервер (вместо этого вы можете разрешать только список Origins / urals, разделенный запятыми, если вы предпочитаете).

Я использовал текущее происхождение клиента вместо * потому что это позволит учетным записям => установить значение Access-Control-Allow-Credentials в значение true, что позволит управлять сеансом кросс-браузера

также вам нужно включить удаление и установку, исправление и варианты глаголов в разделе system.webServer , в противном случае IIS заблокирует их:

         

надеюсь это поможет

После того, как вы столкнулись с одной и той же проблемой в проекте Web API 2 (и не могли использовать стандартные пакеты CORS по причинам, не стоящим здесь), я смог решить эту проблему, выполнив собственный DelagatingHandler:

 public class AllowOptionsHandler : DelegatingHandler { protected override async Task SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { var response = await base.SendAsync(request, cancellationToken); if (request.Method == HttpMethod.Options && response.StatusCode == HttpStatusCode.MethodNotAllowed) { response = new HttpResponseMessage(HttpStatusCode.OK); } return response; } } 

Для конфигурации веб-API:

 config.MessageHandlers.Add(new AllowOptionsHandler()); 

Обратите внимание, что у меня также есть заголовки CORS, включенные в Web.config, похожие на некоторые из других ответов, размещенных здесь:

                  

Обратите внимание: мой проект не включает MVC, а только Web API 2.

Мне удалось преодолеть 405 и 404 ошибки, возникшие при запросах перед полетом ajax, только по специальному коду в global.asax

 protected void Application_BeginRequest() { 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, OPTIONS"); HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept"); HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000"); HttpContext.Current.Response.End(); } } 

PS: Рассмотрите проблемы безопасности при разрешении всего *.

Мне пришлось отключить CORS, поскольку он возвращал заголовок «Access-Control-Allow-Origin», содержащий несколько значений.

Также необходимо это в web.config:

       

И app.pool необходимо установить в интегрированный режим.

У меня была такая же проблема. Для меня было исправлено удаление настраиваемого типа контента из вызова jQuery AJAX. Пользовательские типы контента вызывают запрос перед полетом. Я нашел это:

Браузер может пропустить запрос перед полетом, если выполняются следующие условия:

Метод запроса – GET , HEAD или POST , и

Приложение не устанавливает никаких заголовков запросов, кроме Accept , Accept-Language , Content-Language , Content-Type или Last-Event-ID , а также

Заголовок Content-Type (если установлен) является одним из следующих:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

На этой странице: http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api (в разделе «Предварительные запросы»)

В ASP.NET web api 2 добавлена ​​поддержка CORS. Проверьте ссылку [ http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api ]

  protected void Application_EndRequest() { if (Context.Response.StatusCode == 405 && Context.Request.HttpMethod == "OPTIONS" ) { Response.Clear(); Response.StatusCode = 200; Response.End(); } } 

Я тоже столкнулся с той же проблемой.

Следуйте приведенному ниже шагу, чтобы решить проблему (CORS) в браузерах.

Включите REDRock в ваше решение с помощью ссылки Cors. Включите ссылку WebActivatorEx в решение Web API.

Затем добавьте файл CorsConfig в папку App_Start веб-API.

 [assembly: PreApplicationStartMethod(typeof(WebApiNamespace.CorsConfig), "PreStart")] namespace WebApiNamespace { public static class CorsConfig { public static void PreStart() { GlobalConfiguration.Configuration.MessageHandlers.Add(new RedRocket.WebApi.Cors.CorsHandler()); } } } 

С этими изменениями я смог получить доступ к webapi во всех браузерах.

У меня была такая же проблема, и именно так я ее исправил:

Просто бросьте это в свой web.config:

                     
  • Лучшая практика для возврата ошибок в ASP.NET Web API
  • Как разрешать запросы в веб-Api?
  • Как генерировать и автоматически увеличивать Id с Entity Framework
  • Как вернуть необработанную строку с ApiController?
  • Asp.NET Web API - 405 - HTTP-глагол, используемый для доступа к этой странице, недопустим - как установить сопоставления обработчиков
  • Каковы накладные расходы на создание нового HttpClient на один вызов в клиенте WebAPI?
  • Как настроить пользовательские настройки JsonSerializer для Json.NET в веб-API MVC 4?
  • Dot character '.' в MVC Web API 2 для запроса, например api / people / STAFF.45287
  • Каков рекомендуемый нами способ частичного обновления веб-API?
  • Как создать две строки нижнего колонтитула в jqgrid
  • Выбросить HttpResponseException или вернуть Request.CreateErrorResponse?
  • Interesting Posts

    В чем разница между реализацией и компиляцией в Gradle?

    java.io.IOException: mark / reset не поддерживается

    Автоматически запускать сценарий при входе в Windows

    Связывание только части свойства margin элемента управления WPF

    Комбинации клавиш Fn не работают на ноутбуке Asus на окнах 8

    В чем разница между sudo su – и sudo -i?

    Как автоматически установить USB-накопитель, на который все пользователи могут писать?

    Как определить, было ли приложение .NET скомпилировано в режиме DEBUG или RELEASE?

    Тонкая настройка автозаполнения zsh git

    Что означает среднее значение 0.0.0.0 в таблице маршрутизации?

    Найти class где-нибудь в десятках файлов JAR?

    Можно ли использовать графический процессор nVidia для рендеринга графики, если монитор подключен к видеопорту материнской платы?

    Подождите, пока процесс не завершится

    Необработанное свойство продолжает получать атрибут data-val-required

    Я хочу получить тип переменной во время выполнения

    Давайте будем гением компьютера.