Подтвердить что ты не робот

ASP.NET MVC4 не обрабатывает запросы POST в интегрированном режиме IIS7, но в IIS7.5

У меня есть интересный случай, который я не могу объяснить, и мне нужна помощь в выяснении моей проблемы с IIS7:

Дано:

  • Веб-приложение ASP.NET MVC 4
  • маршрут по умолчанию, зарегистрированный в {controller}/{action}

См. следующий контроллер:

public class ServiceController : Controller
{
    public ActionResult Test()
    {
        return Content("Test");
    }

    [HttpPost]
    public ActionResult Test2()
    {
        return Content("Test2");
    }
}

Кроме того, в Global.asax есть этот код:

protected void Application_EndRequest()
{
    if (Context.Response.StatusCode == 404)
    {
        ExecuteIndexPage();
    }
}

protected void Application_Error(object sender, EventArgs e)
{
    var error = Server.GetLastError();
    ExceptionLogger.Log(error);

    ExecuteIndexPage();
}

Таким образом, всякий раз, когда есть ошибка сервера, это регистрируется. В этом случае и в случае нормального 404 возвращается стартовая страница. Это работает (почти) отлично. Подробнее об этом позже.

Эта настройка дает очень разные типы поведения в IIS7 (Windows Server 2008, производственная среда) и IIS7.5 (Win7 Pro, среда разработки и Windows Server 2008 R2, а также производственная среда).

Учитывая следующую конфигурацию в IIS (обе версии):

  • Web в IIS настроен с использованием пула приложений
  • < modules runAllManagedModulesForAllRequests = "true" / > устанавливается в разделе system.webServer

В IIS 7.5 поведение:

  • Запрос GET в /: возвращает страницу индекса
  • Запрос POST для /: Возвращает индексную страницу
  • Запрос GET в /Service/Test: тест возврата
  • Запрос POST в /Service/Test: тест возврата
  • Запрос GET в /Service/Test 2: Executes Global.asax Application_Error: HttpException: Открытый метод действий Test2 не найден на контроллере MyTestProject.Controllers.ServiceController.
  • Запрос POST в /Service/Test 2: возвращает Test2
  • GET-запрос к чему-то нет пути для: Выполняет Global.asax End_Request.

В IIS 7 вместо этого выполняется следующее:

  • Запрос GET в /: возвращает страницу индекса
  • Запрос POST на страницу IIS 404
  • GET Запрос/Сервис/Тестирование: Тест возврата
  • Запрос на отправку/обслуживание/тестирование: страница IIS 404
  • GET Request to/Service/Test2: Executes Global.asax Application_Error: HttpException: Открытый метод действий Test2 не найден на контроллере MyTestProject.Controllers.ServiceController.
  • Запрос POST/Service/Test2: возвращает страницу IIS 404
  • GET Запрос на то, что нет маршрута для: страницы IIS 404

Итак, IIS 7 и IIS 7.5 отлично работают при использовании запросов GET, за исключением случаев, когда маршрута нет. Когда маршрута нет, IIS 7.5 выполняет конечный запрос Global.asax с кодом состояния 404 и доставляет индексную страницу. IIS 7 выполняет НЕ выполнение запроса окончания Global.asax. Зачем? Я мог (и в настоящее время) работать над этой проблемой, зарегистрировав маршрут {* catchall}, чтобы существовал соответствующий маршрут.

Как только я пытаюсь использовать HTTP POST, IIS 7 работает даже меньше, чем я ожидал.

При отправке запроса IIS 7 не выполняет какой-либо код в моем приложении и напрямую возвращает страницу IIS 404.

Итак, мой вопрос: почему IIS 7 отказывается так сложно обрабатывать запросы POST в моем приложении MVC 4, и что я могу сделать, чтобы он также обрабатывал почтовый запрос?

4b9b3361

Ответ 1

Мы выяснили это - наконец.

Конфигурация по умолчанию вставляет это в файл web.config:

<system.webServer>
  <validation validateIntegratedModeConfiguration="false" />
  <modules runAllManagedModulesForAllRequests="true" />
  <handlers>
    <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
    <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
    <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
    <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
    <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
    <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
  </handlers>
</system.webServer>

Проблема - это "*" . путь, который будет охватывать /test.aspx, но не просто /test.

Если вы измените это на "*" , тогда все запросы будут обрабатываться с помощью ExtensionlessUrlHandler, в том числе для статических файлов, которые больше не будут обслуживаться.

Итак, решение: Удалите глагол POST из записей обработчика и добавьте новые записи для ExtensionlessUrlHandler с путём, установленным на "*" , и только для запросов POST:

    <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
    <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
    <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit_post" path="*" verb="POST" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
    <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit_post" path="*" verb="POST" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
    <add name="ExtensionlessUrlHandler-Integrated-4.0_post" path="*" verb="POST" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />

Идеально удалить те, которые вам не нужны (x86 и x64 в классическом или интегрированном конвейере).

Ответ 2

Возможно, это связано с некоторыми функциями, которые (или не правильно) установлены на IIS 7, что предотвращает правильную работу URL-адреса без продолжения.

Пожалуйста, проверьте следующие пункты:

В диалоговом окне "Включить или отключить Windows" диалогового окна "Программы и функции" панели управления Windows:

  • Перейти к Internet Information Services > World Wide Web Services > Общие функции HTTP
  • Убедитесь, что выбрана опция "Перенаправление ошибок HTTP".
  • Убедитесь, что выбрана опция "Статическое содержимое". После того, как выбран любой вариант, нажмите "ОК", чтобы сохранить изменения.

Ссылка: http://support.microsoft.com/kb/2023146

Ответ 3

Возможно, маршрутизация 7 и 7.5 отличается от передачи POST для действия, у которого нет аргументов, которые могут принимать данные формы сообщения.

Если ваш код никогда не попадает, это указывает на то, что маршрутизация не нашла соответствия для сигнатуры, аргументов и встроенных ограничений, которые она проверяет перед передачей кода.

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