ASP.NET MVC 404 Error Handling

Viewed 166173
6 Answers

Yet another solution.

Add ErrorControllers or static page to with 404 error information.

Modify your web.config (in case of controller).

<system.web>
    <customErrors mode="On" >
       <error statusCode="404" redirect="~/Errors/Error404" />
    </customErrors>
</system.web>

Or in case of static page

<system.web>
    <customErrors mode="On" >
        <error statusCode="404" redirect="~/Static404.html" />
    </customErrors>
</system.web>

This will handle both missed routes and missed actions.

The response from Marco is the BEST solution. I needed to control my error handling, and I mean really CONTROL it. Of course, I have extended the solution a little and created a full error management system that manages everything. I have also read about this solution in other blogs and it seems very acceptable by most of the advanced developers.

Here is the final code that I am using:

protected void Application_EndRequest()
    {
        if (Context.Response.StatusCode == 404)
        {
            var exception = Server.GetLastError();
            var httpException = exception as HttpException;
            Response.Clear();
            Server.ClearError();
            var routeData = new RouteData();
            routeData.Values["controller"] = "ErrorManager";
            routeData.Values["action"] = "Fire404Error";
            routeData.Values["exception"] = exception;
            Response.StatusCode = 500;

            if (httpException != null)
            {
                Response.StatusCode = httpException.GetHttpCode();
                switch (Response.StatusCode)
                {
                    case 404:
                        routeData.Values["action"] = "Fire404Error";
                        break;
                }
            }
            // Avoid IIS7 getting in the middle
            Response.TrySkipIisCustomErrors = true;
            IController errormanagerController = new ErrorManagerController();
            HttpContextWrapper wrapper = new HttpContextWrapper(Context);
            var rc = new RequestContext(wrapper, routeData);
            errormanagerController.Execute(rc);
        }
    }

and inside my ErrorManagerController :

        public void Fire404Error(HttpException exception)
    {
        //you can place any other error handling code here
        throw new PageNotFoundException("page or resource");
    }

Now, in my Action, I am throwing a Custom Exception that I have created. And my Controller is inheriting from a custom Controller Based class that I have created. The Custom Base Controller was created to override error handling. Here is my custom Base Controller class:

public class MyBasePageController : Controller
{
    protected override void OnException(ExceptionContext filterContext)
    {
        filterContext.GetType();
        filterContext.ExceptionHandled = true;
        this.View("ErrorManager", filterContext).ExecuteResult(this.ControllerContext);
        base.OnException(filterContext);
    }
}

The "ErrorManager" in the above code is just a view that is using a Model based on ExceptionContext

My solution works perfectly and I am able to handle ANY error on my website and display different messages based on ANY exception type.

In IIS, you can specify a redirect to "certain" page based on error code. In you example, you can configure 404 - > Your customized 404 error page.

What I can recomend is to look on FilterAttribute. For example MVC already has HandleErrorAttribute. You can customize it to handle only 404. Reply if you are interesed I will look example.

BTW

Solution(with last route) that you have accepted in previous question does not work in much of the situations. Second solution with HandleUnknownAction will work but require to make this change in each controller or to have single base controller.

My choice is a solution with HandleUnknownAction.

Related