Getting 404.0 error for ASP.NET MVC 3 app on IIS 7.0 / Windows Server 2008
Asked Answered
B

6

32

I am attempting to deploy an ASP.NET MVC 3 application to a Windows 2008 x64 server (running IIS 7.0 obviously), and IIS does not want to seem to serve up the content properly. All requests are resulting in a 404.0 error, because the requests are not matching any handler and IIS is attempting to use the StaticFile handler to serve up the requests. The issue seems to be related to .NET 4.0, as I have an MVC 2 application running just fine in an app pool that is configured for the .NET 2.0 runtime.

I have had no issues deploying this same application to IIS 7.5 servers both on Windows 7 and Windows Server 2008 R2.

Prior to deployment, the 2008 server did not have .NET 4.0 or ASP.NET MVC 3 installed, so here are the steps I undertook prior to deploying the application:

  1. Installed .NET 4.0
  2. Ran aspnet_regiis.exe (from the Framework64/v4.0.30319 folder)
  3. Installed ASP.NET MVC 3 using the web platform installer
  4. Applied MS update KB980368 to enable certain IIS 7.0 or IIS 7.5 handlers to handle requests whose URLs do not end with a period

Requests to static resources in the application (JavaScript files, images, etc) go through without a hitch, but any request to an MVC action fails with a 404.0 error. I have noticed that IIS is using the StaticFile handler to handle these requests, which is obviously incorrect. The ASP.NET 4.0 handlers (i.e. ExtensionlessUrl-ISAPI-4.0* handlers) are properly defined as far as I can tell, so I have no idea why/how the request would not be handled by one of these handlers and would fall all the way down to the StaticFile handler.

I also came across the following MS knowledge base article which mentions that you should ensure HTTP Redirection and Static Content Compression are enabled/installed on the server where you are experiencing the 404 errors. I checked, and both features were already enabled for my server. I even tried removing and reinstalling the features to no avail.

At this point I am completely out of ideas for why this is not working properly. I have been able to replicate the issue on 2 different IIS 7.0 servers. What am I missing?

Bilyeu answered 24/2, 2011 at 22:5 Comment(3)
First of all: take a look at Event Viewer, you can save your time to find proper solution.Besiege
@Dario: there is nothing of note in any of the Windows logs in relation to this issue. The worker process is not throwing any exceptions and is running properly on top of the 4.0 runtime. ASP.NET is also not throwing any exceptions, because it is never getting invoked by IIS, since IIS is attempting to use the StaticFile handler to handle the requests.Bilyeu
For the record, all that I required was applying the hotfix (bullet #4).Vector
B
2

The issue ended up being that my code was completely relying on the auto-start functionality that is available only in IIS 7.5. I was able to discover the issue with the help of the Failed Request Tracing feature in IIS, and I have now modified my global.asax.cs file so that the application will be properly initialized, regardless of how/when it is loaded.

Bilyeu answered 28/2, 2011 at 16:8 Comment(2)
how did you end up initializing it in global.asax?Bushwhacker
The class defined in my global.asax.cs file (MvcApplication) implements IProcessHostPreloadClient to take advantage of the IIS 7.5 auto-start functionality. Therefore, I moved all of the code that was in Application_Start to the Preload method. In order to support cases where the auto-start functionality isn't used, I call Preload from ApplicationStart. To ensure Preload only gets called once, I am using a static Boolean field that is checked to determine if the Preload method was previously executed.Bilyeu
H
36

You actually just reminded me that I needed to fix this issue in an enviroment here. If your situation is the same as mine then it's a simple fix.

Just add the following to your web config:

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

Edit: To provide further explanation on the issue at hand. In my case what was happening was when I added custom route mappings IIS was seeing the requests as Folder/Static File requests and thus was skipping over the ASP.NET worker process. This behaves differently under development environment generally because it is being run under the development web server which will also pass all requests through the .net process.

This Web Config entry tells IIS that you have modules that should be run on every web request even if IIS determines it to be a static file or a folder.

Headlight answered 25/2, 2011 at 19:2 Comment(4)
As an aside, if your webservices are in the same web container as your aspx files you will hit a snag because the native modules will not be run and static files (like images) will not be properly served. Putting the webservices elsewhere will probably (hopfully mitigate).Laoag
Had the same issue going from dev environment on win7 to win2k8 live server. Project mixes webforms with mvc3. Solved my problem.Durkheim
I spent an hour on this before I came across this answer and it worked! Why do we need this? and why isn't it in by default if we do?Obsequious
I added an update to my original answer with some further explanation into why it's needed. Why it's not included is that it's normal behavior in IIS to not run static files through the worker process.Headlight
C
3

Please make sure that you are running under IIS 7.0 Integrated mode. If you need to run it under IIS 7.0 Classic mode, you need to perform several actions to make the routes work. Please refer the following blog posts;

http://www.tugberkugurlu.com/archive/running-asp-net-mvc-under-iis-6-0-and-iis-7-0-classic-mode---solution-to-routing-problem

http://www.tugberkugurlu.com/archive/deployment-of-asp-net-mvc-3-rc-2-application-on-a-shared-hosting-environment-without-begging-the-hosting-company

Chor answered 5/3, 2011 at 10:16 Comment(1)
I should have mentioned in the original post that the app pool was using the integrated pipeline. I neglected to mention that, but that was indeed the case. Please see my answer for a description of what the actual cause and solution to my problem was.Bilyeu
B
2

The issue ended up being that my code was completely relying on the auto-start functionality that is available only in IIS 7.5. I was able to discover the issue with the help of the Failed Request Tracing feature in IIS, and I have now modified my global.asax.cs file so that the application will be properly initialized, regardless of how/when it is loaded.

Bilyeu answered 28/2, 2011 at 16:8 Comment(2)
how did you end up initializing it in global.asax?Bushwhacker
The class defined in my global.asax.cs file (MvcApplication) implements IProcessHostPreloadClient to take advantage of the IIS 7.5 auto-start functionality. Therefore, I moved all of the code that was in Application_Start to the Preload method. In order to support cases where the auto-start functionality isn't used, I call Preload from ApplicationStart. To ensure Preload only gets called once, I am using a static Boolean field that is checked to determine if the Preload method was previously executed.Bilyeu
C
2

My solution, after trying EVERYTHING:

Bad deployment, an old PrecompiledApp.config was hanging around my deploy location, and making everything not work.

My final settings that worked:

  • 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;
        }
    }
    
Cage answered 17/3, 2012 at 16:13 Comment(2)
Where is TestRoute Defined, it doesn't compile when I try this because it's missing.Tridimensional
@EricBrown-Cal that TestRoute.Handlers was the name of the namespace that my "PassthroughRouteHandler" lives in. Yours may easily be a different namespace. I suggest just putting in "PassthroughRouteHandler" and letting the intellisense help you with the right "using ..." statementCage
R
0

If you are running your web application on IIS 7.5 or above, please ensure that the role services for IIS are enabled properly. The role services of interest are : ASP.NET, Basic Authentication, HTTP Redirection, ISAPI filters, etc.

You could go to the role services via Add or Remove programs - Turn Windows features on or off. Hope this helps.

Regards, Kiran Banda

Rarefied answered 13/3, 2012 at 8:52 Comment(0)
H
0

I had the same problem. Mine ended up being a failed assembly upon the app starting. I enabled the Fusion Log Viewer to see which assemblies were failing and figured it out. I would have never discovered this since it seemed like an MVC routing issue, but I figured I would post this incase anyone else wasted hours on this problem as well!

Hangeron answered 22/3, 2013 at 22:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.