C# ASP.NET自定义404返回200 OK而不是找不到404
在尝试为Google Webmaster工具设置我的站点后,我发现我的自定义ASP.NET 404页面没有返回404状态代码。它显示了正确的自定义页面,并告诉浏览器一切正常。这是一个软404或假404。谷歌不喜欢这样。所以我找到了很多关于这个问题的文章,但是我想要的解决方案似乎不起作用 我想使用的解决方案是在自定义404页面的代码隐藏页面加载方法中添加以下两行代码C# ASP.NET自定义404返回200 OK而不是找不到404,c#,asp.net,master-pages,http-status-code-404,custom-errors,C#,Asp.net,Master Pages,Http Status Code 404,Custom Errors,在尝试为Google Webmaster工具设置我的站点后,我发现我的自定义ASP.NET 404页面没有返回404状态代码。它显示了正确的自定义页面,并告诉浏览器一切正常。这是一个软404或假404。谷歌不喜欢这样。所以我找到了很多关于这个问题的文章,但是我想要的解决方案似乎不起作用 我想使用的解决方案是在自定义404页面的代码隐藏页面加载方法中添加以下两行代码 Response.Status = "404 Not Found"; Response.StatusCode = 404; 这不管
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中配置自定义错误页。我真的更愿意使用代码隐藏选项,但如果不在设计/布局中添加一个黑客内联代码,我似乎无法使它工作。解决方案:
HTTP/1.1 404 Not Found
Date: Sun, 07 Dec 2008 06:21:20 GMT
问题在于母版页的使用。我通过在页面生命周期的后期设置状态代码使其工作,很明显母版页的呈现正在重置它,因此我覆盖了呈现方法,并在呈现完成后设置它
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);
Response.StatusCode = 404;
}
可以做更多的工作来确定母版页何时设置状态,但我将把这留给您
原创帖子:
HTTP/1.1 404 Not Found
Date: Sun, 07 Dec 2008 06:21:20 GMT
我能够让一个测试web应用程序正常工作,它至少显示了自定义错误页面并返回了404状态代码。我无法告诉你你的应用程序有什么问题,但我可以告诉你我做了什么:
1) 编辑web.config以获取自定义错误:
也就是说,如果我转到任何由Asp.Net处理但不存在的页面扩展,我的fiddler日志会清楚地显示404,下面是标题:
现在,如果我转到Asp.Net未处理的页面(如htm文件),则不会显示自定义页面,并显示由IIS配置的404
这里有一篇文章详细介绍了一些可能对您和您的问题有用的细节,我的测试确实会重定向到新页面,因此请求文件的url几乎丢失(除了查询字符串中的url)
标题间谍响应:
HTTP/1.1 404 Not Found
Date: Sun, 07 Dec 2008 06:21:20 GMT
经过大量测试和故障排除,某些主机提供商可能会干扰返回代码。我可以通过在内容中应用“黑客”来绕过这个问题
<%
// This code is required for host that do special 404 handling...
Response.Status = "404 Not Found";
Response.StatusCode = 404;
%>
这将允许页面返回正确的返回代码,无论发生什么。我有一个类似的问题,我想将自定义页面显示为404(即ASPX),它在本地主机上运行良好,但一旦远程访问者连接,他们就会得到通用的IIS 404 解决这个问题的办法是增加
Response.TrySkipIisCustomErrors = true;
更改Response.StatusCode之前
通过Rick Strahl找到,请尝试调用Response.End()跳过渲染
Response.Status = "404 Not Found";
Response.StatusCode = 404;
Response.End();
return;
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>
我可以通过使用.net 3.5在asp.net webforms中使用以下设置来绕过这个问题 我实现的模式绕过了web.config中的.NET自定义重定向解决方案,因为我已经编写了自己的模式,以在标头中使用正确的HTTP状态代码处理所有场景 首先,web.config的customErrors部分如下所示:
<customErrors mode="RemoteOnly" defaultRedirect="~/error.htm" />
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;
}
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();
}
这段代码将处理错误的责任转移给另一个类。如果错误没有得到处理,而CustomErrors被打开,这意味着我们在生产中遇到了一个错误没有得到处理的情况。我们将在此处清除它,以防止用户看到它,但请将其登录到Elmah,以便了解发生了什么
applicationErrorHandler类如下所示:
<customErrors mode="RemoteOnly" defaultRedirect="~/error.htm" />
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;
}
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();
}
该类本质上使用命令模式为发出的错误类型定位适当的错误处理程序。在这个级别上使用Exception.GetBaseException()非常重要,因为几乎每个错误都会包装在一个更高级别的异常中。例如,从任何aspx页面执行“throw new System.Exception()”将导致在此级别接收HttpUnhandledException,而不是System.Exception
“factory”代码很简单,如下所示:
<customErrors mode="RemoteOnly" defaultRedirect="~/error.htm" />
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;
}
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();
}
公共响应行为工厂()
{
_行为=新字典
{
{typeof(StoreException),()=>newfound302storeresponsebehavior()},
{typeof(HttpUnhandledException),()=>new HttpExceptionResponseBehavior(),
{typeof(HttpException),()=>newhttpexceptionresponsebehavior(),
{typeof(异常),()=>new Found302DefaultResponseBehavior()}
};
}
公共IResponseBehavior GetBehavior(异常)
{
如果(异常==null)抛出新的ArgumentNullException(“异常”);
Func行为;
bool tryGetValue=\u behaviors.tryGetValue(exception.GetType(),out behavior);
//此处的默认值:
如果(!tryGetValue)
_TryGetValue(typeof(Exception),out行为);
if(行为==null)
Elmah.ErrorSignal.FromCurrentContext().Raise(
新的例外(
“危险!没有为此异常定义任何行为,因此用户可能收到死亡的黄色屏幕!”,
例外情况);
返回行为();
}
最后,我得到了一个可扩展的错误处理方案设置。在定义的每一个“行为”中,我都有一个针对错误类型的自定义实现。例如,将检查Http异常的状态代码并进行适当处理。404状态代码将需要