4

The title says it all. There's actually a ton of information on how to do this and I'm very close. I've read several things on google as well as the following stackoverflow posts:

How can I properly handle 404 in ASP.NET MVC?

How can I properly handle 404 in ASP.NET MVC?

Custom error pages on asp.net MVC3

http://blog.davebouwman.com/2011/04/21/custom-404-pages-for-asp-net-mvc-3/

I've got 404's working at the action level. And I'm using the *.aspx suffix on my controllers. If you have a url like

"http://blahblah/AppName/idontexist.aspx"

The custom Error controller is loaded. My issue comes down to controller's that don't have the .aspx and also do not exist. This yields the typical IIS Server 404 html page, which I don't want. Another kink in the works is that I can't really change the IIS configuration itself. I have to handle this via the code/web.config/global.asax (or some other part of the project I haven't thought of).

Here are my web.config entries (this is the root web.config, not the view one):

<httpErrors defaultPath="/Error.aspx/HttpError" errorMode="Custom" existingResponse="Replace" defaultResponseMode="ExecuteURL">
  <remove statusCode="500" subStatusCode="-1" />
  <remove statusCode="404" subStatusCode="-1" />
  <error statusCode="500" path="/Error.aspx/HttpError" responseMode="ExecuteURL" />
  <error statusCode="404" path="/Error.aspx/NotFound" responseMode="ExecuteURL" />
</httpErrors>

<customErrors mode="On"  defaultRedirect="~/Error.aspx/HttpError">
  <error redirect="~/Error.aspx/NotFound" statusCode="404" />
</customErrors>  

And here are my routes in global.asax:

       routes.MapRoute(
            "Default", // Route name
            "{controller}.aspx/{action}/{id}", // URL with parameters
            new { controller = "StartController", action = "StartAction", id = UrlParameter.Optional } // Parameter defaults
        );

        routes.MapRoute(
            "NotFoundController", // Route name
            "{controller}.aspx", // URL with parameters
            new { controller = "Error", action = "NotFound" } // Parameter defaults
        );

        routes.MapRoute(
            "NotFoundController2", // Route name
            "{controller}", // URL with parameters
            new { controller = "Error", action = "NotFound" } // Parameter defaults
        );

        routes.MapRoute(
            "Root", // Route name
            "", // URL with parameters
            new { controller = "StartController", action = "StartAction", id = UrlParameter.Optional } // Parameter defaults
        );

I also think that one snag with using routes to catch these is that I lose the 404 status code; however, because the route points to an action specifically designed for this purpose, I suppose that point is moot.

Anyhow, any thoughts, suggestions, or criticisms would be welcomed. I'm very close here. Thanks!

EDIT 1

I've still been researching this. Is there a way I can define a custom route constraint that will redirect to the Error Controller if the text ".aspx" is not found in the url?

EDIT 2

Doesn't look like that's how constraints are intended to be used. I also tried implementing the

    protected void Application_Error()
    {
    }

method per the implementation at http://blog.davebouwman.com/2011/04/21/custom-404-pages-for-asp-net-mvc-3/, but when I don't specify .aspx for the controller, it looks like the application never gets a chance to throw an error. It looks like that is handled by IIS before my app can even respond to it.

If I could make IIS changes, preferably to just this application's virtual directory entry, would that allow for a more viable solution to this?

If there was just somewhere I could grab the url, search for .aspx, and if it's not found throw a 404 not found, but redirect to the application level 404 page instead of the IIS default, that would be pretty close to ideal.

Thoughts?

EDIT 3

I'm of the opinion that handling this scenario is just not possible unless your application is the root site for the IIS server and not a virtual directory. I noticed that, within IIS 6.0, you can tweak the default IIS error pages. Not only that, you can replace certain cases with a URL. I've tried doing this with a virtual directory site but the default IIS 404 Not found page displays.

So it amounts to: you can handle this on IIS 6 if you have a stupid amount of control over your setup and the site you're doing this for is the root site.

Not very applicable in real world scenarios I imagine.

Community
  • 1
  • 1
jason
  • 2,219
  • 5
  • 33
  • 66
  • 2
    It's unbelievable how troublesome 404 handling can be. – James Lawruk Feb 11 '13 at 16:25
  • Some more help here .. http://www.devcurry.com/2012/06/aspnet-mvc-handling-exceptions-and-404.html – Amitd Feb 11 '13 at 16:38
  • It really is quite amazing. I doubt users of this application would go about tweaking the url, but it doesn't look professional to use that default IIS page. – jason Feb 11 '13 at 16:38
  • Thanks for that link @Amitd. That covers processing on IIS 7. I'm actually doing pretty much all of those things now. I think the issue is IIS 6 specific because my controllers have to have the .aspx in order for IIS 6 to route traffic properly to ASP.NET MVC 3. – jason Feb 11 '13 at 16:44

1 Answers1

1

I don't think this is possible without being able to make changes to IIS. With IIS 6, requests don't enter the ASP.Net realm unless they are mapped to the ASP.Net ISAPI handler (aspnet_isapi.dll). For normal ASP.Net extensions, the mapping is already setup in IIS6 when .Net is installed (.ashx, .aspx, etc). This is why your 404 for a controller that doesn't exist gets the normal IIS 404 page. IIS is looking for a folder that doesn't exist on disk.

In order to get your 404 page handlers to work as expected (this is assuming you COULD make changes to IIS), you'll need to setup what is called a wilcard mapping. This sends all requests to the ASP.Net ISAPI. IIS also needs to be instructed to bypass the check for a physical file, since none will exist in this case. There's a checkbox for that option. I no longer have IIS 6 in front of me, but Option 1 on this site walks you through it:

http://blog.stevensanderson.com/2008/07/04/options-for-deploying-aspnet-mvc-to-iis-6/

I have done this before, it does work. There are some tradeoffs from sending everything to the .Net ISAPI. All static files will be handled by ASP.Net (even images) instead of IIS directly, so just be aware of the implications there.

Hope this helps

Adam Butler
  • 2,733
  • 23
  • 27