【问题标题】:ASP.NET Custom 404 Returning 200 OK Instead of 404 Not FoundASP.NET 自定义 404 返回 200 OK 而不是 404 Not Found
【发布时间】:2010-09-25 17:25:41
【问题描述】:

在尝试为 Google 网站管理员工具设置我的网站后,我发现我的自定义 ASP.NET 404 页面没有返回 404 状态代码。它显示了正确的自定义页面并告诉浏览器一切正常。这被认为是软 404 或假 404。谷歌不喜欢这样。所以我找到了很多关于这个问题的文章,但我想要的解决方案似乎不起作用。

我想要的解决方案是将以下两行添加到自定义 404 页面的 Page_Load 方法后面的代码中。

Response.Status = "404 Not Found";
Response.StatusCode = 404;

这不起作用。页面仍然返回 200 OK。但是我发现,如果我将以下代码硬编码到设计代码中,它将正常工作。

<asp:Content ID="ContentMain" ContentPlaceHolderID="ContentPlaceHolderMaster" runat="server">

<%
    Response.Status = "404 Not Found";
    Response.StatusCode = 404;
%>

 ... Much more code ...

</asp:content>

该页面正在使用母版页。我正在我的 web.config 中配置自定义错误页面。我真的更愿意使用 code behind 选项,但如果不将 hack 内联代码放入设计/布局中,我似乎无法使其工作。

【问题讨论】:

  • 浏览器状态是什么?我使用 Firefox 的插件 Header Spy。
  • 标头间谍响应:HTTP/1.1 404 未找到日期:星期日,2008 年 12 月 7 日 06:21:20 GMT
  • 您使用的是母版页吗?也许就是这样。我将尝试不使用母版页的页面...
  • 不,我没有,但我也可以快速检查一下,我会用一个试试。
  • 是的,就是这样!母版页导致 200 OK

标签: c# asp.net master-pages http-status-code-404 custom-errors


【解决方案1】:

解决方案:

事实证明,问题在于母版页的使用。我通过在页面生命周期的后期设置状态码让它工作,显然母版页的渲染正在重置它,所以我覆盖了渲染方法并在渲染完成后设置它。

protected override void Render(HtmlTextWriter writer)
{
    base.Render(writer);
    Response.StatusCode = 404;
}

可以做更多的工作来确定母版页设置状态的确切时间,但我将把它留给你。


原帖:

我能够让一个测试网络应用正常工作,它至少显示了自定义错误页面并返回了 404 状态代码。我不能告诉你你的应用出了什么问题,但我可以告诉你我做了什么:

1) 针对自定义错误编辑 web.config:

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

2) 添加404.aspx页面,设置状态码为404。

public partial class _04 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Response.StatusCode = 404;
    }
}

就是这样,如果我转到任何由 Asp.Net 处理且不存在的页面扩展,我的提琴手日志清楚地显示 404,这是标题:

HTTP/1.1 404 Not Found
Server: Microsoft-IIS/5.1
Date: Sun, 07 Dec 2008 06:04:13 GMT
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 533

现在如果我转到一个没有被 Asp.Net 处理的页面,比如一个 htm 文件,自定义页面不会显示,并且会显示 IIS 配置的 404。

这里有一篇文章介绍了一些可能对您和您的问题有用的详细信息,我的测试确实重定向到新页面,因此请求文件的 url 几乎丢失了(除了它在查询字符串)。

Google 404 and .NET Custom Error Pages

标头间谍响应:

HTTP/1.1 404 Not Found
Date: Sun, 07 Dec 2008 06:21:20 GMT

【讨论】:

  • Header Spy 是插件 Header Spy for Firefox
  • 静态 .html 自定义错误页面如何工作?
【解决方案2】:

我遇到了类似的问题,我想将自定义页面显示为 404(即 ASPX),它在 localhost 上运行良好,但只要远程访问者连接,他们就会获得通用 IIS 404。

解决方案是添加

Response.TrySkipIisCustomErrors = true;

在更改 Response.StatusCode 之前。

通过 Rick Strahl http://www.west-wind.com/weblog/posts/745738.aspx找到

【讨论】:

    【解决方案3】:

    尝试调用 Response.End() 跳过渲染...

    Response.Status = "404 Not Found";
    Response.StatusCode = 404;
    Response.End();
    return;
    

    【讨论】:

      【解决方案4】:

      IIS 7 解决方案是将其添加到您的 web.config 文件中:

      <system.webServer>
        <httpErrors existingResponse="Replace">
          <remove statusCode="500" subStatusCode="-1" />
          <remove statusCode="404" subStatusCode="-1" />
          <error statusCode="404" prefixLanguageFilePath="" path="404.htm" responseMode="File" />
          <error statusCode="500" prefixLanguageFilePath="" path="500.htm" responseMode="File" />
        </httpErrors>
      </system.webServer>
      

      http://forums.asp.net/t/1563128.aspx/1

      【讨论】:

      • 为我工作!这里唯一可行的解​​决方案,可能是由于您注意到的版本...注意:您只能在此解决方案中使用静态 .htm 文件。
      【解决方案5】:

      经过大量测试和故障排除后,某些托管服务提供商似乎会干扰返回代码。我能够通过在内容中应用“hack”来解决这个问题。

      <%
      // This code is required for host that do special 404 handling...
      Response.Status = "404 Not Found";
      Response.StatusCode = 404;
      %>
      

      这将允许页面无论如何返回正确的返回码。

      【讨论】:

        【解决方案6】:

        我能够通过使用 .NET 3.5 在 asp.net webforms 中使用以下设置来解决此问题。

        我实现的模式绕过了 .NET 在 web.config 中的自定义重定向解决方案,因为我已经编写了自己的模式来处理标题中包含正确 HTTP 状态代码的所有场景。

        首先,web.config 的 customErrors 部分如下所示:

        <customErrors mode="RemoteOnly" defaultRedirect="~/error.htm" />
        

        此设置可确保将 CustomErrors 模式设置为 on,这是我们稍后需要的设置,并为 error.htm 的 defaultRedirect 提供了一个 all-else-fails 选项。当我没有特定错误的处理程序时,这将派上用场,或者数据库连接中断。

        其次,这里是全局 asax 错误事件:

        protected void Application_Error(object sender, EventArgs e)
            {
               HandleError();
            }
        
            private void HandleError()
            {
                var exception = Server.GetLastError();
                if (exception == null) return;
        
                var baseException = exception.GetBaseException();
        
                bool errorHandled = _applicationErrorHandler.HandleError(baseException);
                if (!errorHandled) return;
        
        
                var lastError = Server.GetLastError();
            if (null != lastError && HttpContext.Current.IsCustomErrorEnabled)
            {
                Elmah.ErrorSignal.FromCurrentContext().Raise(lastError.GetBaseException());
                Server.ClearError();
            }
            }
        

        此代码将处理错误的责任转交给另一个类。如果错误没有得到处理并且 CustomErrors 被打开,这意味着我们有一个案例,我们正在生产中并且不知何故没有处理错误。我们将在此处清除它以防止用户看到它,但将其登录到 Elmah 以便我们知道发生了什么。

        applicationErrorHandler 类如下所示:

        public bool HandleError(Exception exception)
                {
                    if (exception == null) return false;
        
                    var baseException = exception.GetBaseException();
        
                    Elmah.ErrorSignal.FromCurrentContext().Raise(baseException);
        
                    if (!HttpContext.Current.IsCustomErrorEnabled) return false;
        
                    try
                    {
        
                        var behavior = _responseBehaviorFactory.GetBehavior(exception);
                        if (behavior != null)
                        {
                            behavior.ExecuteRedirect();
                            return true;
                        }
                    }
                    catch (Exception ex)
                    {
                        Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
                    }
                    return false;
                }
        

        这个类本质上使用命令模式来为发出的错误类型定位适当的错误处理程序。在此级别使用 Exception.GetBaseException() 很重要,因为几乎每个错误都将包装在更高级别的异常中。例如,从任何 aspx 页面执行“throw new System.Exception()”将导致在此级别收到 HttpUnhandledException,而不是 System.Exception。

        “工厂”代码很简单,如下所示:

        public ResponseBehaviorFactory()
            {
                _behaviors = new Dictionary<Type, Func<IResponseBehavior>>
                                {
                                    {typeof(StoreException), () => new Found302StoreResponseBehavior()},
                                    {typeof(HttpUnhandledException), () => new HttpExceptionResponseBehavior()},
                                    {typeof(HttpException), () => new HttpExceptionResponseBehavior()},
                                    {typeof(Exception), () => new Found302DefaultResponseBehavior()}
                                };
            }
        
            public IResponseBehavior GetBehavior(Exception exception)
            {                                                                               
                if (exception == null) throw new ArgumentNullException("exception");
        
                Func<IResponseBehavior> behavior;
                bool tryGetValue = _behaviors.TryGetValue(exception.GetType(), out behavior);
        
                //default value here:
                if (!tryGetValue)
                    _behaviors.TryGetValue(typeof(Exception), out behavior);
        
                if (behavior == null)
                    Elmah.ErrorSignal.FromCurrentContext().Raise(
                        new Exception(
                            "Danger! No Behavior defined for this Exception, therefore the user might have received a yellow screen of death!",
                            exception));
                return behavior();
            }
        

        最后,我有了一个可扩展的错误处理方案设置。在定义的每一个“行为”中,我都有一个错误类型的自定义实现。例如,将检查 Http 异常的状态代码并进行适当处理。 404 状态代码需要 Server.Transfer 而不是 Request.Redirect,以及在标头中写入的相应状态代码。

        希望这会有所帮助。

        【讨论】:

          【解决方案7】:

          您可以使用以下代码:

           Response.TrySkipIisCustomErrors = True
           Response.Status = "404 Not Found"
           Response.AddHeader("Location", "{your-path-to-your-404-page}")
          

          【讨论】:

            猜你喜欢
            • 2016-02-10
            • 1970-01-01
            • 2019-10-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-06-28
            • 2017-10-26
            • 1970-01-01
            相关资源
            最近更新 更多