Jonathan Wood
Jonathan Wood

Reputation: 67345

ASP.NET MVC custom error page not working correctly

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.

Upvotes: 3

Views: 5783

Answers (1)

Win
Win

Reputation: 62301

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();
    } 
}

Upvotes: 4

Related Questions