首页 文章

ASP.NET自定义404返回200 OK而不是404 Not Found

提问于
浏览
75

在尝试为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中配置自定义错误页面 . 我真的宁愿使用后面的代码选项,但我似乎无法在设计/布局中放入黑客内联代码使其工作 .

6 回答

  • 70

    Solution:

    事实证明,问题在于使用母版页 . 我通过在页面生命周期中稍后设置状态代码来实现它,显然主页的呈现正在重置它,所以我覆盖了渲染方法并在渲染完成后设置它 .

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

    可以做更多的工作来确定主页何时设置状态,但我会留给你 .


    Original Post:

    我能够让测试网络应用程序正常工作,它至少显示自定义错误页面并返回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)

    }

    关于它,如果我去任何由Asp.Net处理的页面扩展并且不存在,我的提琴日志清楚地显示404,这里是 Headers :

    找不到HTTP / 1.1 404
    服务器:Microsoft-IIS / 5.1
    日期:太阳,2008年12月7日06:04:13 GMT
    X-Powered-By:ASP.NET
    X-AspNet-版本:2.0.50727
    缓存控制:私有
    内容类型:text / html;字符集= utf-8的
    内容长度:533

    现在,如果我转到未由Asp.Net处理的页面(如htm文件),则不显示自定义页面,并显示IIS配置的404 .

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

    Google 404 and .NET Custom Error Pages

    Header Spy Response:

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

    我有一个类似的问题,我想将自定义页面显示为404(这是ASPX),它在localhost上工作正常,但只要远程访问者连接,他们就会得到通用的IIS 404 .

    对此的解决方案是添加

    Response.TrySkipIisCustomErrors = true;
    

    在更改Response.StatusCode之前 .

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

  • 1

    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

  • 10

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

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

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

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

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

  • 27

    通过使用.NET 3.5在asp.net webforms中使用以下设置,我能够解决这个问题 .

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

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

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

    此设置确保将CustomErrors模式设置为on,这是我们稍后需要的设置,并为error.htm的defaultRedirect提供all-else-failed选项 . 当我没有针对特定错误的处理程序时,或者在数据库连接断开的情况下,这将派上用场 .

    其次,这是全局的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,以及在标头中写入的相应状态代码 .

    希望这可以帮助 .

相关问题