Option One:
is to build an Errors Controller with a "NotFound" view along with a "Unknown" view. This will take anything that is a 500 Server error or a 404 NotFound error and redirect you to the appropriate URL. I don't totally love this solution as the visitor is always redirected to an error page.
http://example.com/Error/Unknown
<customErrors mode="On" defaultRedirect="Error/Unknown">
<error statusCode="404" redirect="Error/NotFound" />
<error statusCode="500" redirect="Error/Unknown" />
</customErrors>
- wwwroot/
- Controllers
- Views/
- Error/
- NotFound.aspx
- Unknown.aspx
Option Two:
I Definitely don't prefer this method (as it is basically reverting back to web forms, The second option is to simply have a static Error.aspx page and ignore the route in MVC), but it works none the less. What you're doing here is ignoring a "Static" directory, placing your physical Error pages in there, and skirting around MVC.
routes.IgnoreRoute("/Static/{*pathInfo}"); //This will ignore everything in the "Static" directory
- wwwroot/
- Controllers/
- Static/
- Views/
Option Three:
The third option (THIS IS MY FAVORITE) is to return an Error View from whatever view is catching the error. This would require you to code up Try/Catch blocks along the way for "known" errors and then you can use HandleError for the unknown errors that might creep up. What this will do is preserve the originally requested URL but return the ERROR view.
EXAMPLE:
http://example.com/Products/1234 will show a details page for ProductID 1234
http://example.com/Products/9999 will show a NotFound error page because ProductID 9999 doesn't exist
http://example.com/Errors/NotFound "should" never be shown because you handle those errors individually in your controllers.
Web.Config
<customErrors mode="On">
</customErrors>
Controller
// Use as many or as few of these as you need
[HandleError(ExceptionType = typeof(SqlException), View = "SqlError")]
[HandleError(ExceptionType = typeof(NullReferenceException), View = "NullError")]
[HandleError(ExceptionType = typeof(SecurityException), View = "SecurityError")]
[HandleError(ExceptionType = typeof(ResourceNotFoundException), View = "NotFound")]
Public Class ProductController: Controller{
public ViewResult Item(string itemID)
{
try
{
Item item = ItemRepository.GetItem(itemID);
return View(item);
}
catch()
{
return View("NotFound");
}
}
}
Folder Structure
- wwwroot/
- Controllers/
- Shared/
- NotFound.aspx
- NullError.aspx
- SecurityError.aspx
- SqlError.aspx
- Views/
Option Four:
The last option would be that you build your own custom filter for things like ResourceNotFoundException
and attach it to your controller class. This will do the exact same thing as above but with the added benefit of sending the error code down the line to the client as well.
Richard Dingwall talks about it on his blog.