ASP.NET自定义404返回200确定,而不是找不到404

试图设置我的网站谷歌网站pipe理员工具后,我发现我的自定义ASP.NET 404页面没有返回404状态代码。 它显示正确的自定义页面,并告诉浏览器,一切正常。 这是考虑软404或虚假404。谷歌不喜欢这个。 所以我在这个问题上发现了很多文章,但是我想要的解决scheme似乎没有工作。

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

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

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

 <asp:Content ID="ContentMain" ContentPlaceHolderID="ContentPlaceHolderMaster" runat="server"> <% Response.Status = "404 Not Found"; Response.StatusCode = 404; %> ... Much more code ... </asp:content> 

该页面正在使用母版页。 我在我的web.configconfiguration自定义错误页面。 我真的宁愿使用后面的代码选项,但我似乎无法使它的工作没有在devise/布局中的黑客内联代码。

解:

事实certificate,问题是使用母版页。 我通过在页面生命周期中稍后设置状态码来工作,显然母版页的渲染重置了它,所以我重写渲染方法并在渲染完成后设置它。

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

可以做更多的工作来准确地找出母版页的设置状态,但是我会把它留给你。


原帖:

我能够得到一个testingWeb应用程序工作正常,至less显示自定义错误页面,并返回一个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文件一样,自定义页面不会显示,并显示由IISconfiguration的404。

这里有一些可能对你和你的问题有用的更详细的信息,我的testing做了一个redirect到新页面,所以请求的文件的URL几乎丢失(除了在查询string中) 。

Google 404和.NET自定义错误页面

标题间谍回应:

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

我有一个类似的问题,我想显示自定义页面为404(这是ASPX),它在本地主机上运行良好,但只要远程访问者连接,他们将获得通用的IIS 404。

解决这个问题是补充

 Response.TrySkipIisCustomErrors = true; 

在更改Response.StatusCode之前。

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

IIS 7的解决scheme是将其添加到您的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

尝试调用Response.End()来跳过呈现…

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

经过多次testing和排除故障,似乎某些托pipe服务提供商可能会干扰返回码。 我能够通过在内容中应用“黑客”来解决这个问题。

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

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

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

我已经实现的模式绕过了web.config中的.NET自定义redirect解决scheme,因为我已经编写了自己的代码来处理头中正确的HTTP状态代码的所有场景。

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

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

此设置可确保将CustomErrors模式设置为打开,稍后将需要该设置,并为error.htm的defaultRedirect提供all-else-failures选项。 当我没有处理特定错误的处理程序,或者在断开的数据库连接的某些行时,这会派上用场。

其次,这是全球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被打开,这意味着我们有一个情况,我们正在生产,不知何故错误没有得到处理。 我们将在这里清除它,以防止用户看到它,但logging在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; } 

这个类基本上使用命令模式来为发出的错误types定位适当的error handling程序。 在这个级别使用Exception.GetBaseException()是很重要的,因为几乎每个错误都会被包装在一个更高级的exception中。 例如,从任何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(); } 

最后,我有一个可扩展的error handlingscheme设置。 在每个定义的“行为”中,我都有一个自定义的错误types实现。 例如,将检查一个Httpexception的状态代码并进行适当的处​​理。 一个404状态代码将需要一个Server.Transfer而不是一个Request.Redirect,以及写在标题中的相应的状态码。

希望这可以帮助。