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>
尝试调用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,以及写在标题中的相应的状态码。
希望这可以帮助。