在asp.net 2.0网站上,编写错误页面的最佳方法是什么。我在以下位置看过以下部分:
<customErrors mode="RemoteOnly" defaultRedirect="~/Pages/Common/DefaultRedirectErrorPage.aspx">
void Application_Error(object sender, EventArgs e)
{
}
我没有得到如何以最佳方式使用它们来进行错误处理。
请指导我最好的方法。
答案 0 :(得分:9)
在我的全局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 - &gt; 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-handles-404-requests/
返回正确的状态代码
默认处理404的页面 错误页面不会返回404状态 代码到浏览器。它显示了 您提供给的错误消息 用户但没有任何额外的 将页面标记为的信息 错误页面。
这称为软404.软404 页面不如那些页面好 返回404状态代码,因为 返回404状态代码让 访问你的文件的任何东西 页面是一个错误页面而不是一个 你站点的真实页面。这主要是 因为那时对搜索引擎很有用 他们知道他们应该去世 他们的索引中的页面,所以用户不会 关注您网站的死链接 结果页。
返回404状态代码的页面是 也适用于错误检测 因为它们会记录在你的 服务器日志,如果你有意外 404错误,它们很容易找到。 这是404错误的一个例子 Google网站站长工具中的报告:
<强> EDITS 强>
需要写吗? global.asax中的server.clearerror()? 它有什么影响
为什么在web.config中我们应该写error.aspx 两次,状态码为500,另一次是 defaultredirect
你能告诉我error.aspx和lost.aspx的代码。
答案 1 :(得分:3)
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);
}