在 ASP.NET 中实现 404 的最佳方法

Posted

技术标签:

【中文标题】在 ASP.NET 中实现 404 的最佳方法【英文标题】:Best way to implement a 404 in ASP.NET 【发布时间】:2010-10-14 14:26:18 【问题描述】:

我正在尝试确定在标准 ASP.NET Web 应用程序中实现 404 页面的最佳方式。我目前在 Global.asax 文件中的 Application_Error 事件中捕获 404 错误并重定向到友好的 404.aspx 页面。问题是请求看到 302 重定向,然后是 404 页面丢失。有没有办法绕过重定向并立即响应包含友好错误消息的 404?

Googlebot 等网络爬虫是否关心对不存在页面的请求是否返回 302 后跟 404?

【问题讨论】:

【参考方案1】:

在 Global.asax 的 OnError 事件中处理这个问题:

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");
    
  

在你的错误页面中,你应该确保你正确设置了状态码:

// 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";

您还可以很好地处理这里的各种其他错误代码。

Google 通常会遵循 302,然后遵守 404 状态代码 - 因此您需要确保在错误页面上返回该代码。

【讨论】:

完美。我忘记了 Server.Transfer() 方法。我已经在使用 Application_Error 事件,所以现在我只调用 Server.Transfer() 而不是 Response.Redirect()。 至少在 IIS 7 中,上述内容甚至没有 302 临时重定向。对我来说,问题是发现 Server.ClearError() 对于 404 是必不可少的(否则仍然进行重定向,而不是转移)。 404.htm页面是否应该是.aspx页面,以便您可以在代码隐藏中添加Response.StatusCode = 404? @codeulike:很好,这是一个 MCMS 实例的副本,它使用 ISAPI 过滤器将 url 映射到其数据库中的内容,因此忽略了扩展名。有问题的页面后面确实有一个 .aspx 页面。 TrySkipIisCustomErrors 正是我所需要的。不错。【参考方案2】:

您可以使用 web.config 将 404 错误发送到自定义页面。

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

【讨论】:

我试过这个,它似乎仍然以 302 响应 FileNotFound.htm。也许 FileNotFound.htm 返回了 404,但初始响应仍然是 302 重定向。你看到同样的东西吗? 这本身会导致 302(至少对于 IIS 7)。应该: 1. 对 404 执行上述自定义错误。 2. 在 Application_Error(global.asax 或错误模块)中检查 404,如果是:Server.ClearError(); Server.Transfer("/page-not-found.aspx"); 3.在404页面:Response.Status = "404 Not Found"; Response.StatusCode = 404; 如果将 redirectMode="ResponseRewrite" 添加到 它将重定向。在发送“404 Not Found”状态代码之前,它也不会发送“302 Found”状态代码。您可以随时查看 msdn 的链接:msdn.microsoft.com/en-us/library/h0hfz6fc.aspx【参考方案3】:

最简单的答案:不要在代码中这样做,而是 configure IIS instead。

【讨论】:

【参考方案4】:

我也遇到了 302 而不是 404。我设法通过执行以下操作来修复它:

控制器:

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

            return View();
        

查看:

向用户显示一些错误消息。

web.config:

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

最后是 RouthConfig:

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

【讨论】:

【参考方案5】:

我非常喜欢这种方法:它创建一个视图来处理所有错误类型并覆盖 IIS。

[1]:从 Web.config 中删除所有“customErrors”和“httpErrors”

[2]:检查 'App_Start/FilterConfig.cs' 看起来像这样:

public class FilterConfig

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    
        filters.Add(new HandleErrorAttribute());
    

[3]:在'Global.asax'中添加这个方法:

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]: 添加'Controllers/ErrorPageController.cs'

public class ErrorPageController : Controller

    public ActionResult Error(int statusCode, Exception exception)
    
        Response.StatusCode = statusCode;
        ViewBag.StatusCode = statusCode + " Error";
        return View();
    

[5]:在“视图/共享/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

【讨论】:

这很整洁:)【参考方案6】:

你在任何地方都用这个吗?

 Response.Status="404 Page Not Found"

【讨论】:

【参考方案7】:

我可以看到在 web.config 中设置 404 页面是一种很好的干净方法,但它最初仍会以 302 重定向响应到错误页面。例如,如果您导航到:

https://***.com/x.aspx

您将通过 302 重定向重定向到:

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

我想要发生的事情是这样的:

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

没有重定向。对丢失 URL 的请求会返回 404 状态代码和友好的错误消息。

【讨论】:

【参考方案8】:

您可以将 IIS 本身配置为返回特定页面以响应任何类型的 http 错误(包括 404)。

【讨论】:

【参考方案9】:

我认为最好的方法是在您的 web.config 中使用自定义错误结构,如下所示,这让您可以连接页面以简单有效的方式处理所有不同的 HTTP 代码。

  <customErrors mode="On" defaultRedirect="~/500.aspx">
     <error statusCode="404" redirect="~/404.aspx" />
     <error statusCode="500" redirect="~/500.aspx" />
  </customErrors>

【讨论】:

以上是关于在 ASP.NET 中实现 404 的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

以干净的方式在 Asp.Net Core API 中实现 ProblemDetails 的最佳方法

在 ASP.NET MVC 2 中实现 DropDownList 的最佳方式?

在 ASP.NET MVC 应用程序中实现细粒度安全(即授权)的最佳机制是啥?

在 asp.net 中锁定缓存的最佳方法是啥?

Asp.Net Web API 阻止 404 页面上的任意文本

在 ASP.Net 应用程序中实现通用错误处理的简单方法