ASP.NET MVC4在IIS7集成模式下不处理POST请求,但在IIS7.5中

Seb*_*ter 13 iis-7 iis-7.5 asp.net-mvc-4

我有一个有趣的案例,我无法解释,我需要帮助弄清楚我在IIS7上的问题:

鉴于:

  • ASP.NET MVC 4 Web应用程序
  • 注册到{controller}/{action}的默认路由

请参阅以下控制器:

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

    [HttpPost]
    public ActionResult Test2()
    {
        return Content("Test2");
    }
}
Run Code Online (Sandbox Code Playgroud)

另外,在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();
}
Run Code Online (Sandbox Code Playgroud)

因此,只要出现服务器错误,就会记录下来.在这种情况下,在正常404的情况下,返回起始页面.这工作(几乎)很好.以后更多.

此设置在IIS7(Windows Server 2008,生产环境)和IIS7.5(Win7 Pro,开发环境和Windows Server 2008 R2,以及生产环境)上提供了非常不同的行为.

鉴于IIS中的以下配置(两个版本):

  • IIS中的Web使用集成模式 ASP.NET 4应用程序池进行配置
  • <modules runAllManagedModulesForAllRequests ="true"/>在system.webServer部分中设置

IIS 7.5中,行为是:

  • GET请求到/:返回索引页面
  • POST请求到/:返回索引页面
  • GET请求/ Service/Test:返回Test
  • POST请求/ Service/Test:返回Test
  • GET请求/ Service/Test2:执行Global.asax Application_Error:HttpException:在控制器'MyTestProject.Controllers.ServiceController'上找不到公共操作方法'Test2'.
  • POST请求/ Service/Test2:返回Test2
  • 请求没有路由的请求:执行Global.asax End_Request.

IIS 7中,行为改为:

  • GET请求到/:返回索引页面
  • POST请求到/:IIS 404页面
  • GET请求/服务/测试:返回测试
  • POST请求/服务/测试:IIS 404页面
  • GET请求/ Service/Test2:执行Global.asax Application_Error:HttpException:在控制器'MyTestProject.Controllers.ServiceController'上找不到公共操作方法'Test2'.
  • POST请求/ Service/Test2:返回IIS 404页面
  • GET请求没有路由的东西:IIS 404页面

因此,IIS 7和IIS 7.5在使用GET请求时工作得很好,除非没有路由.当没有路由时,IIS 7.5执行状态代码为404的Global.asax结束请求并传递索引页.IIS 7不会NOT执行的Global.asax结束请求.为什么?我可以(并且目前正在)通过注册{*catchall}路由解决此问题,以便存在匹配的路由.

一旦我尝试使用HTTP POST,IIS 7确实比我预期的工作更少.

在POST请求时,IIS 7不会在我的应用程序中执行任何代码,并直接返回IIS 404页面.

所以我的问题是:为什么IIS 7在我的MVC 4应用程序中拒绝如此难以处理POST请求,我该怎么办才能让它处理post请求?

Seb*_*ter 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>
Run Code Online (Sandbox Code Playgroud)

问题是“*”。路径,它将覆盖/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" />
Run Code Online (Sandbox Code Playgroud)

理想情况下,删除不需要的那些(经典管道与集成管道中的 x86 和 x64)。