在IIS 7.0 / Windows Server 2008上运行的ASP.NET MVC 3应用程序出现404.0错误

32
我正在尝试将一个ASP.NET MVC 3应用程序部署到一个运行IIS 7.0的Windows 2008 x64服务器上,但是IIS似乎无法正确提供内容。所有请求都导致404.0错误,因为请求没有匹配到任何处理程序,而IIS正在尝试使用StaticFile处理程序提供请求。这个问题似乎与.NET 4.0有关,因为我有一个在为.NET 2.0运行时配置的应用程序池中运行良好的MVC 2应用程序。
我在Windows 7和Windows Server 2008 R2上的IIS 7.5服务器上部署了这个相同的应用程序没有遇到任何问题。
在部署之前,2008服务器没有安装.NET 4.0或ASP.NET MVC 3,因此在部署应用程序之前,我采取了以下步骤:
1. 安装.NET 4.0 2. 运行aspnet_regiis.exe(来自Framework64/v4.0.30319文件夹) 3. 使用Web平台安装程序安装ASP.NET MVC 3 4. 应用MS更新KB980368以启用某些IIS 7.0或IIS 7.5处理程序来处理URL不以句点结尾的请求
应用程序中静态资源的请求(JavaScript文件、图像等)可以顺利进行,但对MVC操作的任何请求都会失败并出现404.0错误。我注意到IIS正在使用StaticFile处理程序来处理这些请求,这显然是不正确的。据我所知,ASP.NET 4.0处理程序(即ExtensionlessUrl-ISAPI-4.0*处理程序)已经正确定义,因此我不知道为什么/如何请求不会由其中一个处理程序处理,并且会一直落到StaticFile处理程序。
我还遇到了以下MS知识库文章,其中提到您应确保在您遇到404错误的服务器上启用/安装HTTP重定向和静态内容压缩。我检查过了,这两个功能已经在我的服务器上启用了。我甚至尝试删除并重新安装这些功能,但没有效果。
目前我完全没有想法为什么这不正常工作。我已经能够在两个不同的IIS 7.0服务器上复制该问题。我错过了什么?

首先:查看事件查看器,您可以节省时间找到适当的解决方案。 - Dariusz
@Dario:关于这个问题,Windows日志中没有任何值得注意的内容。工作进程没有抛出任何异常,并且在4.0运行时上正常运行。ASP.NET也没有抛出任何异常,因为它从未被IIS调用,由于IIS尝试使用StaticFile处理程序来处理请求。 - Justin Holzer
1
记录一下,我所需要的只是应用热修补程序(第四个项目符号)。 - xanadont
6个回答

36

你其实提醒了我需要在这里的环境中修复这个问题。如果您的情况与我的相同,则可以轻松解决。

只需将以下内容添加到您的Web配置文件中:

<system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />

编辑:就这个问题进一步解释一下。在我的情况下,当我添加自定义路由映射时,IIS会将请求视为文件夹/静态文件请求,因此跳过ASP.NET worker进程。在开发环境下,它的行为通常是不同的,因为它在开发Web服务器上运行,该服务器还将所有请求通过.net进程传递。

这个Web Config条目告诉IIS,您有一些模块应该在每个Web请求上运行,即使IIS确定它是静态文件或文件夹也应该如此。


1
顺便提一下,如果您的 Web 服务与您的 aspx 文件位于同一个 Web 容器中,那么您将会遇到问题,因为本地模块不会运行,并且静态文件(如图像)将无法正确提供。将 Web 服务放在其他位置可能会缓解这个问题。 - Dan Doyon
从win7的开发环境到win2k8的生产服务器时遇到了同样的问题。该项目混合使用webforms和mvc3。解决了我的问题。 - Jeroen
我在找到这个答案之前花了一个小时,而它确实有效!为什么我们需要这个?如果是这样的话,为什么它不是默认开启的呢? - GONeale
我在原回答中添加了一个更新,进一步解释了为什么需要它。之所以没有包含它是因为在IIS中不通过工作进程运行静态文件是正常行为。 - Michael Merrell

3

我应该在原始帖子中提到应用程序池正在使用集成管道。 我忽略了这一点,但事实确实如此。 请参阅我的答案,了解实际原因和解决方案的描述。 - Justin Holzer

2

在尝试了所有方法后,我找到了解决方案:

糟糕的部署,一个旧的PrecompiledApp.config文件一直存在于我的部署位置,导致所有东西都无法正常工作。

最终可行的设置如下:

  • IIS 7.5, Win2k8r2 x64,
  • Integrated mode application pool
  • Nothing changes in the web.config - this means no special handlers for routing. Here's my snapshot of the sections a lot of other posts reference. I'm using FluorineFX, so I do have that handler added, but I did not need any others:

    <system.web>
      <compilation debug="true" targetFramework="4.0" />
      <authentication mode="None"/>
    
      <pages validateRequest="false" controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/>
      <httpRuntime requestPathInvalidCharacters=""/>
    
      <httpModules>
        <add name="FluorineGateway" type="FluorineFx.FluorineGateway, FluorineFx"/>
      </httpModules>
    </system.web>
      <system.webServer>
        <!-- Modules for IIS 7.0 Integrated mode -->
        <modules>
          <add name="FluorineGateway" type="FluorineFx.FluorineGateway, FluorineFx" />
        </modules>
    
        <!-- Disable detection of IIS 6.0 / Classic mode ASP.NET configuration -->
        <validation validateIntegratedModeConfiguration="false" />
      </system.webServer>
    
  • Global.ashx: (only method of any note)

    void Application_Start(object sender, EventArgs e) {
        // Register routes...
        System.Web.Routing.Route echoRoute = new System.Web.Routing.Route(
              "{*message}",
            //the default value for the message
              new System.Web.Routing.RouteValueDictionary() { { "message", "" } },
            //any regular expression restrictions (i.e. @"[^\d].{4,}" means "does not start with number, at least 4 chars
              new System.Web.Routing.RouteValueDictionary() { { "message", @"[^\d].{4,}" } },
              new TestRoute.Handlers.PassthroughRouteHandler()
           );
    
        System.Web.Routing.RouteTable.Routes.Add(echoRoute);
    }
    
  • PassthroughRouteHandler.cs - this achieved an automatic conversion from http://andrew.arace.info/stackoverflow to http://andrew.arace.info/#stackoverflow which would then be handled by the default.aspx:

    public class PassthroughRouteHandler : IRouteHandler {
    
        public IHttpHandler GetHttpHandler(RequestContext requestContext) {
            HttpContext.Current.Items["IncomingMessage"] = requestContext.RouteData.Values["message"];
            requestContext.HttpContext.Response.Redirect("#" + HttpContext.Current.Items["IncomingMessage"], true);
            return null;
        }
    }
    

TestRoute定义在哪里?当我尝试运行它时,由于缺失而无法编译。 - Eric Brown - Cal
@EricBrown-Cal,TestRoute.Handlers是我“PassthroughRouteHandler”所在的命名空间名称。你的可能是不同的命名空间。我建议只需输入“PassthroughRouteHandler”,然后让智能感知帮助你找到正确的“using…”语句。 - Andrew Arace

2
问题的根源在于我的代码完全依赖于仅在IIS 7.5中可用的自动启动功能。通过使用IIS中的失败请求跟踪功能,我能够发现问题,并且现在我已经修改了global.asax.cs文件,以便应用程序可以正确初始化,无论何时/如何加载它。

你是怎么在 global.asax 中初始化它的? - jdiaz
2
我的global.asax.cs文件中定义的类(MvcApplication)实现了IProcessHostPreloadClient接口,以利用IIS 7.5的自动启动功能。因此,我将所有在Application_Start中的代码移动到Preload方法中。为了支持不使用自动启动功能的情况,我从ApplicationStart调用Preload。为了确保Preload只被调用一次,我使用了一个静态布尔字段来检查Preload方法是否已经执行过。 - Justin Holzer

0

我曾经遇到过同样的问题。最终发现是应用程序启动时出现了一个失败的程序集。我启用了Fusion日志查看器来查看哪些程序集失败并找到了解决方法。如果不是因为这个问题看起来像是MVC路由问题,我可能永远都不会发现这个问题。但我想发布这篇文章,以防其他人也在这个问题上浪费时间。


0
如果您正在运行基于IIS 7.5或更高版本的Web应用程序,请确保已正确启用IIS的角色服务。感兴趣的角色服务包括:ASP.NET、基本身份验证、HTTP重定向、ISAPI筛选器等。
您可以通过添加或删除程序 - 打开或关闭Windows功能来访问角色服务。 希望这可以帮助您。
此致, Kiran Banda

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接