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

时间:2013-02-05 15:50:05

标签: iis-7 asp.net-mvc-4 iis-7.5

我有一个我无法解释的有趣案例,我需要帮助弄清楚我在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");
    }
}

此外,在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(两个版本)中给出以下配置:

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

IIS 7.5 中,行为是:

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

IIS 7 中,行为改为:

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

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

当我尝试使用HTTP POST时,IIS 7的工作效果甚至低于我的预期。

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

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

3 个答案:

答案 0 :(得分: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,但不是简单/测试。

如果将其更改为“*”,则所有请求都将由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)。

答案 1 :(得分:0)

这可能与IIS 7上未安装(或未正确)的某些功能有关,这些功能会阻止无扩展URL正常工作。

请检查以下项目:

在Windows控制面板“程序和功能”应用程序的“打开或关闭Windows功能”对话框中:

  1. 转到互联网信息服务&gt;万维网服务&gt;常见的HTTP功能
  2. 确保选中“HTTP错误重定向”选项。
  3. 确保选中“静态内容压缩”选项。选择任一选项后,单击“确定”保存更改。
  4. 参考:http://support.microsoft.com/kb/2023146

答案 2 :(得分:0)

对于将POST交给没有可以接受帖子表单数据的参数的操作,7和7.5路由可能不同。

如果您的代码永远不会被命中,则表明路由没有找到匹配签名,参数和内置约束,它在切换到代码之前检查。

下一步可能是尝试将参数添加到POST以接受模型,即使您没有传递该模型。结果显然模型将为null。