【问题标题】:ASP.NET MVC4 not handling POST requests in IIS7 integrated mode, but in IIS7.5ASP.NET MVC4 不在 IIS7 集成模式下处理 POST 请求,而是在 IIS7.5 中
【发布时间】:2013-01-20 14:36:59
【问题描述】:

我有一个我无法解释的有趣案例,我需要帮助找出我在 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 中的以下配置(两个版本):

  • IIS 中的 Web 是使用 集成模式 ASP.NET 4 应用程序池配置的
  • 在 system.webServer 部分设置

IIS 7.5 中,行为是:

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

IIS 7 中,行为改为:

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

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

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

当 POST 请求时,IIS 7 不会在我的应用程序中执行任何代码,而是直接返回一个 IIS 404 页面。

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

【问题讨论】:

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


    【解决方案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 功能”对话框中:

      1. 转到 Internet 信息服务 > 万维网服务 > 通用 HTTP 功能
      2. 确保选择了“HTTP 错误重定向”选项。
      3. 确保选中“静态内容压缩”选项。选择任一选项后,单击“确定”以保存更改。

      参考:http://support.microsoft.com/kb/2023146

      【讨论】:

        【解决方案3】:

        可能 7 和 7.5 的路由在将 POST 传递给没有参数可以接受 POST 表单数据的操作方面有所不同。

        如果您的代码从未被命中,则表明路由未找到与签名、参数和内置约束相匹配的签名、参数和内置约束,在移交给代码之前会检查这些约束。

        也许下一步是尝试将参数添加到 POST 以接受模型,即使您没有传入该模型。模型显然会因此为空。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-04-13
          • 1970-01-01
          • 2011-04-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-10-08
          相关资源
          最近更新 更多