ASP.NET MVC 3 - Handling Not Found with ASP.NET MVC 3

A web application built using ASP.NET MVC can break in a few different places when handling a URL it does not recognise. By default, your user will receive a rather unfriendly default ASP.NET error page. Ideally, you should be catching these “not found” errors and displaying a more useful page.

First let's look at the places you need to watch for broken URLs in an ASP.NET MVC3 application. Then I'll introduce a simple library you can use to handle all this.

1. Missing action method on a controller

Imagine we have a controller called HomeController and a default route of “{controller}/{action}” in the route table. Then a URL with the path “home/epicfail” will be routed to the HomeController and look for an action method called “EpicFail”.

If the action method does not exist then the Controller's default HandleUnknownAction method is called and throws an HttpException, with 404 as the status code. ASP.NET then shows its nasty error page.

A possible solution is to override HandleUnknownAction and render your friendly 404 page instead of throwing an exception.

2. Missing controller

Given a route of “{controller}/{action}”, the URL “missing/example” will cause a search for a controller called “MissingController”. If this controller is not found then a 404 HttpException is thrown.

To catch this, you need to have a custom controller factory (IControllerFactory) that returns a special “not found” controller to handle the broken request.

3. Unknown route

If the URL does not match any of the defined routes then a 404 HttpException is thrown. To intercept this you need to create a “catch-all” route. For example, “{*any}” and map this to some controller that will then show your friendly 404 page.

4. Deliberate not found response

Sometimes your action methods need to say that a resource is not found. For example, a row with the given ID was not found in the database anymore. You may want to reuse a common “Not Found” view.

 Introducing NotFoundMvc

Correctly handling all the possible “not found” causes is non-trivial and is likely to be repeated in many MVC applications. Therefore I created the NotFoundMvc library.

Add the library to your project via nuget: Install-Package NotFoundMvc

Or get the source code on GitHub:
github.com/andrewdavey/NotFoundMvc

Referencing the NotFoundMvc.dll assembly from your web application project will cause it to auto-start with the application. (Thank you
PreApplicationStartMethod .)

NotFoundMvc will:

- Handle all “not found” causes and render a friendly error view
- Add a catch-all route to the end of the route table to handle unrecognised routes
- Wrap the controller factory to handle missing controllers
- Wrap the ActionInvoker of each created controller to handle missing actions
- Provide a NotFoundViewResult you can use to return a NotFound view from your actions

The wrapper objects pass through to the original implementations. So if, for example, you're using a custom controller factory already, it will still work as before.

Installing the nugget package will also add a basic NotFound.cshtml view to the ~\Views\Shared folder. So if you're not using nugget, then please create this view manually. If you're using aspx views, or something else, change the file extension as required.

The output of the NotFound view must be at least 512 bytes in length, otherwise IE and Chrome will show their own error page! The default NotFound.cshtml view includes padding spaces to avoid this.

The source code for NotFoundMvc contains a sample project to demonstrate basic usage.