There are many articles on SO and the web in attempts to handle 404's and exceptions gracefully.
From what I have read the best advice seems to be have a route for 404's like so:
routes.MapRoute(
"404-PageNotFound",
"{*url}",
new { controller = "ErrorController", action = "PageNotFound" }
);
Then for other errors have the HandleError
atribute on the Controller and have CustomErrors turned on in web.config so it goes to the error.cshtml page.
However I have read that if you get a exception that does not set the HTTP code to 500 the HandleError will not work.
Can we finally produce an answer/best practice that handles 404's/Exceptions/ASP.Net errors where we can apply to this to all our projects?
Thanks
I use a simple error handling setup. Nice and simple. More info can be found at http://erictopia.com/2010/04/building-a-mvc2-template-part-7-custom-web-errors-and-adding-support-for-elmah/
Install ELMAH and have it handle all the errors.
Next create an Error controller. Add a catch all route like this:
routes.MapRoute(
"ErrorHandler", // Route name
"{*path}", // URL
new { controller = "Error", action = "Index" }
);
Then in web.config add this section:
<customErrors mode="RemoteOnly" defaultRedirect="/Error/Index">
<error statusCode="403" redirect="/Error/NoAccess" />
<error statusCode="404" redirect="/Error/NotFound" />
</customErrors>
No need to set up a 404 route.
In global asax application start, set up a global filter to catch 404 where the controller exists but not the action, or if an action returns a 404 result.
filters.Add(new HttpNotFoundFilterAttribute { Order = 99 });
where the filter is an ActionFilterAttribute with this override:
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.Result !=null &&
(filterContext.Result.GetType() == typeof(HttpNotFoundResult) )
{
//You can transfer to a known route for example
filterContext.Result = new TransferResult(SomeAction, SomeController);
}
}
And also in Application_Error, in case no controller exists:
Exception ex = Server.GetLastError();
string uri = null;
if (Context != null && Context.Request != null)
{
uri = Context.Request.Url.AbsoluteUri;
}
Exception baseEx = ex.GetBaseException();
var httpEx = ex as HttpException;
if ((httpEx != null && httpEx.GetHttpCode()==404)
|| (uri != null && Context.Response.StatusCode == 404) )
{ /* do what you want. */
//Example: show some known url
Server.ClearError();
Server.TransferRequest(transferUrl);
}
To avoid handling 404 for static resources, you should install SP1 on Windows 7 or windows 2008 R2 to upgrade IIS7 and set in web.config:
...
<modules runAllManagedModulesForAllRequests="false">
...