Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return 404 page without redirect

I'm trying to get my 404s working correctly but can't figure out how to get it quite right.

Initially I set my the following in my Statup Configure method:

app.UseMvc(routes =>
{
    // routing here
});

app.Use((context, next) =>
{
    context.Response.StatusCode = 404;
    return next();
});

app.UseStatusCodePagesWithRedirects("/error/{0}");

Which redirected to a page where I showed the error. However the status codes were 302 > 200. I set the /error/{code} action to return the relevant status code, so now I have 302 > 404 which (due to the 302 redirect) makes it look as though the /error/404 page doesn't exist (which it does).

What I want to do is to return the error page without the redirect, so that attempting to request /doesntexist will return 404 and display the error page.

The other thing I tried is to use app.UseStatusCodePagesWithReExecute("/error/{0}"); which does return a 404 without changing the url but displays only a blank page rather than my error page

like image 276
Jordan Wallwork Avatar asked Aug 17 '16 12:08

Jordan Wallwork


People also ask

Should 404 pages redirect?

404s should not always be redirected. 404s should not be redirected globally to the home page. 404s should only be redirected to a category or parent page if that's the most relevant user experience available. It's okay to serve a 404 when the page doesn't exist anymore (crazy, I know).

How do you trigger a 404?

There are several reasons why you might be getting an HTTP 404 code: One typical trigger for an error 404 message is when the page has been deleted from the website. The page was moved to another URL and the redirection was done incorrectly. You entered an incorrect URL address.


1 Answers

In my app, I'm doing it like this:

// custom 404 and error page - this preserves the status code (ie 404)
app.UseStatusCodePagesWithReExecute("/Home/Error/{0}");

My HomeController has this action method

public IActionResult Error(int statusCode)
{
    if (statusCode == 404)
    {
        var statusFeature = HttpContext.Features.Get<IStatusCodeReExecuteFeature>();
        if (statusFeature != null)
        {
            log.LogWarning("handled 404 for url: {OriginalPath}", statusFeature.OriginalPath);
        }

    }
    return View(statusCode);
}

and my view is like this:

@model int

@{
    switch (Model)
    {
        case 400:
            ViewData["Icon"] = "fa fa-ban text-danger";
            ViewData["Title"] = "Bad Request";
            ViewData["Description"] = "Your browser sent a request that this server could not understand.";
            break;
        case 401:
            ViewData["Icon"] = "fa fa-ban text-danger";
            ViewData["Title"] = "Unauthorized";
            ViewData["Description"] = "Sorry, but the page requires authentication.";
        break;
        case 403:
            ViewData["Icon"] = "fa fa-exclamation-circle text-danger";
            ViewData["Title"] = "Forbidden";
            ViewData["Description"] = "Sorry, but you don't have permission to access this page.";
        break;
        case 404:
            ViewData["Icon"] = "fa fa-exclamation-circle text-danger";
            ViewData["Title"] = "Page Not Found";
            ViewData["Description"] = "Sorry, but the page you were looking for can't be found.";
            break;
        case 500:
        default:
            ViewData["Icon"] = "fa fa-exclamation-circle text-danger";
            ViewData["Title"] = "Unexpected Error";
            ViewData["Description"] = "Well, this is embarrassing. An error occurred while processing your request. Rest assured, this problem has been logged and hamsters have been released to fix the problem.";
            break;
    }
}

<div class="jumbotron text-center">
    <header>
        <h1><span aria-hidden="true" class="@ViewData["Icon"]"></span> @ViewData["Title"]</h1>
    </header>
    <p>@ViewData["Description"]</p>
    <a class="btn btn-primary btn-lg" href="@Url.RouteUrl("/")"><span aria-hidden="true" class="fa fa-home"></span> Site Home</a>
</div>

as mentioned by @khellang, the order of middleware is important, and this should be before app.UseMvc

like image 119
Joe Audette Avatar answered Nov 15 '22 10:11

Joe Audette