iis-7 - ASP.NET MVC4 不在 IIS7 集成模式下处理 POST 请求,而是在 IIS7.5 中

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

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

鉴于:

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

  • 请参阅以下 Controller :
    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:在 Controller “MyTestProject.Controllers.ServiceController”上找不到公共(public)操作方法“Test2”。
  • 对/Service/Test2 的 POST 请求:返回 Test2
  • 对没有路由的事物的 GET 请求:执行 Global.asax End_Request。

  • IIS 7 相反,行为是:
  • 对/的 GET 请求:返回索引页
  • POST 请求到/:IIS 404 页面
  • 对/Service/Test 的 GET 请求:返回 Test
  • 对/Service/Test 的 POST 请求:IIS 404 页面
  • 对/Service/Test2 的 GET 请求:执行 Global.asax Application_Error:HttpException:在 Controller “MyTestProject.Controllers.ServiceController”上找不到公共(public)操作方法“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 的工作量甚至低于我的预期。

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

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

    最佳答案

    我们想通了——终于。

    默认配置将其插入到 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)。

    关于iis-7 - ASP.NET MVC4 不在 IIS7 集成模式下处理 POST 请求,而是在 IIS7.5 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14711414/

    相关文章:

    asp.net-mvc - 使用 Linq to Sql 选择多个表

    c# - 有没有办法在 ASP.NET 中将身份验证从一个 Web 应用程序持久保存到另一个嵌套的 Web 应用程序?

    yii2 - 如何在 IIS 上正确配置 web.config 以发布 YII2 Advanced

    IIS 7 日志与自定义

    iis-7 - IIS 7.5 经典 ASP 错误处理与 IIS 6 不同

    asp.net-mvc-4 - 使用 webdav 和 asp .net mvc 打开 MS Word 文档

    javascript - 用户名检查不适用于具有多个寄存器模型 (mvc) 的表单

    asp.net-mvc - 登录后出现404.0错误。 Asp.Net MVC 和 IIS 7.5

    c# - 如何在 Asp WebAPI 应用程序中实现长时间运行的后台任务

    asp-classic - 丢失 ASP session 变量 IIS 6.0 至 7.5