13

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

  • IIS 中的 Web 使用集成模式ASP.NET 4 应用程序池进行配置
  • <modules runAllManagedModulesForAllRequests="true" /> 在 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 页面
  • 对 /Service/Test 的 GET 请求:返回测试
  • 对 /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 的工作量甚至低于我的预期。

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

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

4

3 回答 3

1

We figured it out - finally.

The default configuration inserts this in the 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>

The problem is the "*." path, which would cover /test.aspx but not simply /test.

If you change this to "*", then all requests will be handled by the ExtensionlessUrlHandler, including those to static files which will not be served anymore.

So the solution is: Remove the POST verb from the handler entries and add new entries for the ExtensionlessUrlHandler with the path set to "*" and only for POST requests:

    <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" />

Ideally remove the ones you don't need (x86 and x64 in classic vs. integrated pipeline).

于 2014-01-13T12:14:32.903 回答
0

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

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

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

于 2013-11-21T08:36:13.413 回答
0

This might have to do with some features that are not (or not correctly) installed on IIS 7 which prevent extensionless URL's from working correctly.

Please check the following items:

In the "Turn Windows Features On or Off" dialog box of the Windows Control Panel "Programs and Features" application:

  1. Go to Internet Information Services > World Wide Web Services > Common HTTP Features
  2. Make sure that the "HTTP Error Redirection" option is selected.
  3. Make sure that the "Static Content Compression" option is selected. After either option has been selected, click "OK" to save changes.

Reference: http://support.microsoft.com/kb/2023146

于 2013-05-10T21:24:26.510 回答