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, и что я могу сделать, чтобы он также обрабатывал почтовый запрос?
Ответы
Ответ 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.