Best way to implement a 404 in ASP.NET

人走茶凉 提交于 2019-11-26 20:17:13
Zhaph - Ben Duguid

Handle this in your Global.asax's OnError event:

protected void Application_Error(object sender, EventArgs e){
  // An error has occured on a .Net page.
  var serverError = Server.GetLastError() as HttpException;

  if (serverError != null){
    if (serverError.GetHttpCode() == 404){
      Server.ClearError();
      Server.Transfer("/Errors/404.aspx");
    }
  }
}

In you error page, you should ensure that you're setting the status code correctly:

// If you're running under IIS 7 in Integrated mode set use this line to override
// IIS errors:
Response.TrySkipIisCustomErrors = true;

// Set status code and message; you could also use the HttpStatusCode enum:
// System.Net.HttpStatusCode.NotFound
Response.StatusCode = 404;
Response.StatusDescription = "Page not found";

You can also handle the various other error codes in here quite nicely.

Google will generally follow the 302, and then honour the 404 status code - so you need to make sure that you return that on your error page.

You can use the web.config to send 404 errors to a custom page.

    <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
        <error statusCode="403" redirect="NoAccess.htm" />
        <error statusCode="404" redirect="FileNotFound.htm" />
    </customErrors>

Easiest answer: don't do it in code, but configure IIS instead.

I also faced with 302 instead 404. I managed to fix it by doing the following:

Controller:

public ViewResult Display404NotFoundPage()
        {
            Response.StatusCode = 404;  // this line fixed it.

            return View();
        }

View:

Show some error message to user.

web.config:

<customErrors mode="On"  redirectMode="ResponseRedirect">
      <error statusCode="404" redirect="~/404NotFound/" />
</customErrors>

Lastly, the RouthConfig:

routes.MapRoute(
             name: "ErrorPage",
             url: "404NotFound/",
             defaults: new { controller = "Pages", action = "Display404NotFoundPage" }
         );

I really like this approach: it creates a single view to handle all error types and overrides IIS.

[1]: Remove all 'customErrors' & 'httpErrors' from Web.config

[2]: Check 'App_Start/FilterConfig.cs' looks like this:

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }
}

[3]: in 'Global.asax' add this method:

public void Application_Error(Object sender, EventArgs e)
{
    Exception exception = Server.GetLastError();
    Server.ClearError();

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

    if (exception.GetType() == typeof(HttpException))
    {
        routeData.Values.Add("statusCode", ((HttpException)exception).GetHttpCode());
    }
    else
    {
        routeData.Values.Add("statusCode", 500);
    }

    Response.TrySkipIisCustomErrors = true;
    IController controller = new ErrorPageController();
    controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
    Response.End();
}

[4]: Add 'Controllers/ErrorPageController.cs'

public class ErrorPageController : Controller
{
    public ActionResult Error(int statusCode, Exception exception)
    {
        Response.StatusCode = statusCode;
        ViewBag.StatusCode = statusCode + " Error";
        return View();
    }
}

[5]: in 'Views/Shared/Error.cshtml'

@model System.Web.Mvc.HandleErrorInfo
@{
    ViewBag.Title = (!String.IsNullOrEmpty(ViewBag.StatusCode)) ? ViewBag.StatusCode : "500 Error";
}

 <h1 class="error">@(!String.IsNullOrEmpty(ViewBag.StatusCode) ? ViewBag.StatusCode : "500 Error"):</h1>


//@Model.ActionName
//@Model.ContollerName
//@Model.Exception.Message
//@Model.Exception.StackTrace

:D

Do you use this anywhere?

 Response.Status="404 Page Not Found"
Ben Mills

I can see that setting up the 404 page in the web.config is a nice clean method, BUT it still initially responds with a 302 redirect to the error page. As an example, if you navigate to:

https://stackoverflow.com/x.aspx

you'll be redirected via a 302 redirect to:

https://stackoverflow.com/404?aspxerrorpath=/x.aspx

What I want to happen is this:

http://www.cnn.com/x.aspx

There's no redirect. A request for the missing URL returns a 404 status code with a friendly error message.

You can configure IIS itself to return specific pages in response to any type of http error (404 included).

I think the best way is to use the custom errors construct in your web.config like below, this let's you wire up pages to handle all of the different HTTP codes in a simple effective manner.

  <customErrors mode="On" defaultRedirect="~/500.aspx">
     <error statusCode="404" redirect="~/404.aspx" />
     <error statusCode="500" redirect="~/500.aspx" />
  </customErrors>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!