Jared
Jared

Reputation: 416

MVC 5 Error Handling Web.Config customErrors

I was exploring different types of error handling and was trying to setup some of my own error handling.

My first attempt was to use customErrors section in the web.config file. I have setup two error sections. One for 404 errors and the other for 403. In one of my controllers I set the Response.StatusCode = 404; and postman receives a status of 404. However, my page is served up and the status is never caught.

Maybe I am missing something. Below is my sample.

Controller:

public ActionResult PostAuditReport()
{
        Response.StatusCode = 404;
        return View(new PostAuditReportMessage { stage_directory = "PostAuditReport" });
}

Web.Config:

<customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="~/Error/Error.cshtml">
  <error statusCode="404" redirect="~/Error/NotFound"/>
  <error statusCode="403" redirect="~/Error/BadRequest"/>
</customErrors>

Upvotes: 1

Views: 4130

Answers (2)

Win
Win

Reputation: 62260

public ActionResult PostAuditReport()
{
   Response.StatusCode = 404;
    return View(new PostAuditReportMessage { stage_directory = "PostAuditReport" });
}

Above code works the way it should. It serves PostAuditReport's View with status code 404 instead of 200. If you want to serve 404 view with custom message, you want the following -

Global.asax.cs

The trick is not to use Redirect for 404 - NotFound to avoid round trip.

The following code will render NotFound view for 404 while maintaining the original URL in browser.

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

   // Log exception to database if you want to.

    // 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 ErrorController();

        var routeData = new RouteData();
        routeData.Values.Add("controller", "Error");
        routeData.Values.Add("action", "NotFound");

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

ErrorController

You will need to create separate Views for the following Action Methods.

public class ErrorController : Controller
{    
    [AllowAnonymous]
    public ActionResult BadRequest()
    {
        Response.StatusCode = 403;
        Response.TrySkipIisCustomErrors = true;

        return View();
    }    

    [AllowAnonymous]
    public ActionResult NotFound()
    {
        Response.StatusCode = 404;
        Response.TrySkipIisCustomErrors = true;

        return View();
    }

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

        return View();
    } 
}

*FYI: You cannot direct to Error.cshtml. By default, IIS won't serve .cshtml due to security reason.

It should be something like this -

<customErrors defaultRedirect="~/Error/Error" mode="On">
  <error statusCode="404" redirect="~/Error/NotFound"/>
  <error statusCode="403" redirect="~/Error/BadRequest"/>
</customErrors>

Upvotes: 2

middelpat
middelpat

Reputation: 2585

You are setting the statuscode of the response to 404, but you still serve the view as the response. Try causing a 404 using an exception:

throw new HttpException(404, "Not Found");

Using this you'll cause the execution of your code to stop with an 404 error which will be picked up by the errorhandling. (in this case in your web.config)

Upvotes: 1

Related Questions