在 asp.net 2.0 网站中,编写错误页面的最佳方式是什么。我在以下位置看到了以下部分:
<customErrors mode="RemoteOnly" defaultRedirect="~/Pages/Common/DefaultRedirectErrorPage.aspx">
void Application_Error(object sender, EventArgs e)
{
}
我没有得到如何以最佳方式使用它们来处理错误。
请指导我最好的方法。
在 asp.net 2.0 网站中,编写错误页面的最佳方式是什么。我在以下位置看到了以下部分:
<customErrors mode="RemoteOnly" defaultRedirect="~/Pages/Common/DefaultRedirectErrorPage.aspx">
void Application_Error(object sender, EventArgs e)
{
}
我没有得到如何以最佳方式使用它们来处理错误。
请指导我最好的方法。
在我的全局 asax 中,我总是检查它是什么类型的 http 错误......
然后转移到 web.config 中指定的正确错误页面 我喜欢处理通常的嫌疑人,404(丢失页面)和 500(服务器错误)
http 状态码的一些背景知识对于了解处理它们的原因很重要:
http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
我的 web.config 看起来像这样
<customErrors mode="On" defaultRedirect="~/error.aspx" >
<error statusCode="404" redirect="~/lost.aspx" />
<error statusCode="500" redirect="~/error.aspx" />
</customErrors>
我丢失的页面中有逻辑试图找到他们可能一直在寻找的页面的链接,以及其他一些格式。
我的错误页面有点不同,显示了一些错误消息,
所以我处理两者的方式不同。
取决于您是否拥有站点的安全区域,您可能想要处理 401/403 ?
protected void Application_Error(object sender, EventArgs e)
{
var context = Context;
var error = context.Server.GetLastError() as HttpException;
var statusCode = error.GetHttpCode().ToString();
// we can still use the web.config custom errors information to
// decide whether to redirect
var config = (CustomErrorsSection)WebConfigurationManager.GetSection("system.web/customErrors");
if (config.Mode == CustomErrorsMode.On ||
(config.Mode == CustomErrorsMode.RemoteOnly && context.Request.Url.Host != "localhost"))
{
// set the response status code
context.Response.StatusCode = error.GetHttpCode();
// Server.Transfer to correct ASPX file for error
if (config.Errors[statusCode] != null)
{
HttpContext.Current.Server.Transfer(config.Errors[statusCode].Redirect);
}
else
HttpContext.Current.Server.Transfer(config.DefaultRedirect);
}
}
我服务器转移的原因是这样搜索引擎不会感到困惑,并保持我的网站管理员日志有意义......如果你重定向你返回一个 http 状态 302,它告诉浏览器转到重定向到的页面......然后这个下一页返回状态码 200 ( ok )。
302 --> 200 ,甚至 302 --> 404 具有不同的含义,只是 404...
然后说我的 404 错误页面,我确保我设置了 http 错误的状态代码:
protected void Page_PreRender(object sender, EventArgs e)
{
Response.Status = "404 Lost";
Response.StatusCode = 404;
}
这篇文章对我很有帮助,我知道我想做什么,但我喜欢这段代码如何看待 web.config 设置...... http://helephant.com/2009/02/improving-the-way-aspnet-处理 404 请求/
返回正确的状态码
默认情况下,处理 404 错误页面的页面不会向浏览器返回 404 状态代码。它显示您提供给用户的错误消息,但没有任何额外信息将该页面标记为错误页面。
这称为软 404。软 404 页面不如返回 404 状态码的页面好,因为返回 404 状态码会让任何访问您的文件的人认为该页面是错误页面,而不是您网站的真实页面。这对搜索引擎最有用,因为他们知道应该从索引中删除死页,这样用户就不会从结果页中将死链接跟踪到您的网站。
返回 404 状态代码的页面对于错误检测也很有用,因为它们会记录在您的服务器日志中,因此如果您遇到意外的 404 错误,很容易找到它们。以下是 Google 网站管理员工具中的 404 错误报告示例:
编辑
是否需要在 global.asax 中编写 server.clearerror() ?它有什么影响
为什么在 web.config 中我们应该写两次 error.aspx,一次是状态码 500,另一次是 defaultredirect
能否也告诉我error.aspx和lost.aspx的代码。
BigBlondeViking 的响应对我很有效,只是我发现它没有处理 403(当您尝试直接访问 /Scripts/ 或 /Content/ 目录时 ASP 会生成该响应)。看来这不是作为异常传播的,因此不可捕获在 Application_Error 处理中。(这被外部公司认定为“安全漏洞” - 不要让我开始这样做!)
protected void Application_PostRequestHandlerExecute(object sender, EventArgs e)
{
if (!Context.Items.Contains("HasHandledAnError")) // have we alread processed?
{
if (Response.StatusCode > 400 && // any error
Response.StatusCode != 401) // raised when login is required
{
Exception exception = Server.GetLastError(); // this is null if an ASP error
if (exception == null)
{
exception = new HttpException((int)Response.StatusCode, HttpWorkerRequest.GetStatusDescription(Response.StatusCode));
}
HandleRequestError(exception); // code shared with Application_Error
}
}
}
我还在我的常见错误处理中做了一个小改动。当我们使用 ASP.NET MVC 时,我想显式调用控制器,并传递异常对象。这允许我访问异常本身,以便我可以根据代码记录/发送详细的电子邮件;
public ActionResult ServerError(Exception exception)
{
HttpException httpException = exception as HttpException;
if(httpException != null)
{
switch (httpException.GetHttpCode())
{
case 403:
case 404:
Response.StatusCode = 404;
break;
}
// no email...
return View("HttpError", httpException);
}
SendExceptionMail(exception);
Response.StatusCode = 500;
return View("ServerError", exception);
}
为了传递异常 OBJECT(不仅仅是消息和代码),我显式调用了控制器:
protected void HandleRequestError(Exception exception)
{
if (Context.Items.Contains("HasHandledAnError"))
{
// already processed
return;
}
// mark as processed.
this.Context.Items.Add("HasHandledAnError", true);
CustomErrorsSection customErrorsSection = WebConfigurationManager.GetWebApplicationSection("system.web/customErrors") as CustomErrorsSection;
// Do not show the custom errors if
// a) CustomErrors mode == "off" or not set.
// b) Mode == RemoteOnly and we are on our local development machine.
if (customErrorsSection == null || !Context.IsCustomErrorEnabled ||
(customErrorsSection.Mode == CustomErrorsMode.RemoteOnly && Request.IsLocal))
{
return;
}
int httpStatusCode = 500; // by default.
HttpException httpException = exception as HttpException;
if (httpException != null)
{
httpStatusCode = httpException.GetHttpCode();
}
string viewPath = customErrorsSection.DefaultRedirect;
if (customErrorsSection.Errors != null)
{
CustomError customError = customErrorsSection.Errors[((int)httpStatusCode).ToString()];
if (customError != null && string.IsNullOrEmpty(customError.Redirect))
{
viewPath = customError.Redirect;
}
}
if (string.IsNullOrEmpty(viewPath))
{
return;
}
Response.Clear();
Server.ClearError();
var httpContextMock = new HttpContextWrapper(Context);
httpContextMock.RewritePath(viewPath);
RouteData routeData = RouteTable.Routes.GetRouteData(httpContextMock);
if (routeData == null)
{
throw new InvalidOperationException(String.Format("Did not find custom view with the name '{0}'", viewPath));
}
string controllerName = routeData.Values["controller"] as string;
if (String.IsNullOrEmpty(controllerName))
{
throw new InvalidOperationException(String.Format("No Controller was found for route '{0}'", viewPath));
}
routeData.Values["exception"] = exception;
Response.TrySkipIisCustomErrors = true;
RequestContext requestContext = new RequestContext(httpContextMock, routeData);
IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
IController errorsController = factory.CreateController(requestContext, controllerName);
errorsController.Execute(requestContext);
}