3

I'm trying to configure ASP.NET MVC custom error pages.

I added an Error controller with Index and PageNotFound actions. I also added the following to the <system.web> section of my web.config file.

<customErrors mode="On" defaultRedirect="~/Error">
  <error statusCode="404" redirect="~/Error/PageNotFound"/>
  <error statusCode="500" redirect="~/Error" />
</customErrors>

If I type in a URL such as http://www.example.com/Home/BadPage, I do in fact see my error handler.

However, can anyone help me understand the following issues and how to work around them?

  1. In the case above, it appears that the result code returned to the browser is 200 and not 404. So crawlers such as Google's would have no indication the URL was not found.
  2. In some cases, if my controller action determines the URL is not valid, the action will return HttpNotFound() as the result. But when this happens, my custom error handler page is not displayed. Instead it shows a generic 404 page that appears to be from IIS.

I'm using the current versions of Visual Studio and MVC.

1 Answer 1

4

In addition to setting inside web.config, you also want to check whether Exception is HttpException 404 inside Application_Error.

<customErrors defaultRedirect="~/Common/Error" mode="On">
  <error statusCode="404" redirect="~/Common/PageNotFound"/>
</customErrors>

Global.asax.cs

protected void Application_Error(object sender, EventArgs e)
{
    var exception = Server.GetLastError();

    // Process 404 HTTP errors
    var httpException = exception as HttpException;
    if (httpException != null && httpException.GetHttpCode() == 404)
    {
        Response.Clear();
        Server.ClearError();
        Response.TrySkipIisCustomErrors = true;

        IController controller = new CommonController();

        var routeData = new RouteData();
        routeData.Values.Add("controller", "Common");
        routeData.Values.Add("action", "PageNotFound");

        var requestContext = new RequestContext(
             new HttpContextWrapper(Context), routeData);
        controller.Execute(requestContext);
    }
}

CommonController

You also want to return Response.StatusCode = 404; inside PageNotFound action method.

public class CommonController : Controller
{
    [AllowAnonymous]
    public ActionResult PageNotFound()
    {
        Response.StatusCode = 404;
        Response.TrySkipIisCustomErrors = true;

        return View();
    }

    [AllowAnonymous]
    public ActionResult Error()
    {
        Response.StatusCode = 503;
        Response.TrySkipIisCustomErrors = true;

        return View();
    } 
}
Sign up to request clarification or add additional context in comments.

3 Comments

I'm kind of getting this to work. Couple of questions: 1) Why not just use Response.Redirect("/Common/PageNotFound") in your error handler?, and 2) when your code does Response.Redirect(), I don't think that returns the error code (such as 404) to the browser for the original URL.
1) Ideally, we want to maintain the original URL in client browser while displaying 404 message. Response.Redrect causes the round trip to the server, and doesn't maintain the original URL. 2) You can test it using Fiddler.
Oh, I see. You are avoiding the redirect. Right you are.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.