我的Global.aspx中有以下内容用于处理错误:
void Application_Error(object sender, EventArgs e)
{
Exception exception = Server.GetLastError();
if (exception != null)
{
//Log
if (HttpContext.Current.Server != null)
{
HttpContext.Current.Server.Transfer("/siteerror.aspx");
}
}
}
这在很大程度上起作用,但有时不会进入Server.Transfer。由于某种原因,HttpContext.Current.Server为null。我想出了这种情况发生的地方:用户控件和业务逻辑类中发生错误。我在这里错过了什么吗?
由于
答案 0 :(得分:2)
Application_Error块可以在应用程序生命周期之间的任何时间捕获异常。
应用程序生命周期是会话生命周期的父级,因为您可以理解单个应用程序中可以有多个会话。
因此,在创建会话之前或会话到期之后,您可能会遇到HttpContext.Current null。
如果要编写特定于会话的错误重定向,则应始终检查当前HttpContext的Null。
您还可以使用Server.GetLastError来了解发生的错误详细信息,并通过web.config中的CustomError标记重定向错误页面
请参阅以下链接
答案 1 :(得分:1)
应用程序错误可以随时发生 - 包括没有连接时。
例如,如果后台线程正在处理并导致异常。
答案 2 :(得分:0)
这是应用程序中最精细的异常处理级别。我们非常熟悉try-catch块,可以将它们包装在一组代码上,如果发生异常,则它将处理此异常。异常处理块是这样的。
try
{
throw new InsufficientMemoryException();
}
catch (Exception ex)
{
throw new Exception("");
}
catch
{
throw;
}
由于这不是基本的异常处理文章,因此我们不会深入研究该示例。
页面级别
我们可以在页面级别实现异常处理机制。好处是我们不需要将所有代码都包装在try-catch-finally块中;我们可以说,这是集中页面的异常处理机制。 无论异常发生在哪里,它将通过以下代码捕获。
void Page_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
}
要确定异常类型,我们需要使用Server类的GetLastError()函数,该函数将返回异常类型对象,并且通过检查该对象,我们可以做出进一步的决定,是在此页面中处理异常还是将其抛出到更高的水平。如果更高的级别,那么更高的级别呢?
应用程序级别
是的,这是异常处理机制的顶层。如果我们在Global.asax页面中实现它。我们都熟悉Global.asax页面,该页面主要处理与Global(应用程序)和会话相关的对象。如果我们在此页面中实现Application_Error()事件,则所有未处理的异常都将在此处堆叠,我们可以对错误做出最高决策。我们将忽略它还是将其记录或通过邮件发送。这是Global.asax页面中Application_Error()的实现。
protected void Application_Error(object sender, EventArgs e)
{
//Catch Exception in Central place
Exception exceptionObject = Server.GetLastError();
}
异常检测机制与页面级异常处理机制非常相似。我们正在使用Server类的GetLastError()函数,该函数将返回一个异常类型对象。现在,我们有责任进一步研究异常类型及其可能的解决方案。
好的,我们已经看到了ASP.NET应用程序中异常处理机制的三个级别。现在,显而易见的问题是,我们是否应该在单个应用程序中实现所有这些级别?为什么不?他们可以在同一应用程序中和平地调整自己,而且他们像团队一样工作。如果一个未能处理异常,则另一个尝试。如果再次失败,则它的上级权限将尝试执行此操作。
好的,下一个问题是底层是否能够解决该异常?会更高吗?不,如果较低的级别能够处理异常,那么它将不会冒泡(调用)其较高的级别。让我们澄清一下概念。
在一个ASP.NET页面中,我编写了这段代码。
try
{
throw new DivideByZeroException();
}
catch (DivideByZeroException ex)
{
}
catch
{
throw;
}
在我们从try块引发DivideByZero异常的地方,然后通过传递适当的Exception对象类型来捕获它。因此catch块可以处理异常。现在,使情况变得更加复杂。在此页面中,我们将在页面级别保留以下代码以进行全局异常处理。
void Page_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
}
我们将看到代码在异常处理时不会执行。由于本机try-catch块足以处理异常,因此无需调用其上级机制,并且出于相同的原因,如果存在的话,将跳过应用程序级异常机制。 很好,到目前为止,我们已经了解了异常机制的级别并阐明了其一些概念。现在,我们将在一个示例应用程序中实现所有这些级别,并且我们将实现我们的目标。让我们逐步进行。
第1步:在块级创建异常并使用try-catch换行
该步骤非常简单,我们已经做了很多次。在一个try块中,我们引发一个InsufficientMemoryException,并且假设该try块将引发“ DivideByZeroException”,如果我们的假设正确,则可以处理该异常,否则将其抛出更高的级别。
try
{
throw new InsufficientMemoryException();
}
catch (DivideByZeroException ex)
{
//show Message
}
catch
{
throw;
}
更高级别的机制在哪里?页面级别。我们将在下一步中实现它。
第2步:在页面级实施异常处理机制
这是下一级别的异常处理。我们已经实现了一个Page_Error()事件,该事件可以捕获此页面中所有未处理的异常。现在,我们期望该页面仅引发ObjectDisposeException,并且乐观的说,我们保留了仅处理此类异常的机制。 (这是一个非常愚蠢的实现,我们不应该这样做。)无论如何,如果异常是任何其他类型,那么我们将其抛出更高的处理机制。
void Page_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
if (ex is ObjectDisposedException)
{
//Log this Exception
}
else
throw new HttpUnhandledException("Unhandle Exception", ex);
}
下一个更高的权限是应用程序级异常处理机制。
第3步:在Global.asax页面中实现Application_Error()
protected void Application_Error(object sender, EventArgs e)
{
//Catch Exception in Global place
Exception exceptionObject = Server.GetLastError();
try
{
if (exceptionObject != null)
{
if (exceptionObject.InnerException != null)
{
exceptionObject = exceptionObject.InnerException;
}
switch (exceptionObject.GetType().ToString())
{
case "System.Threading.ThreadAbortException":
HttpContext.Current.Server.ClearError();
break;
default:
LogException(exceptionObject);//Custom method to log error
break;
}
}
}
catch { }//Avoiding further exception from exception handling
}
LogException()函数是一个存根,用于通过超出我们的核心解释来实现更多内容。在这里。
public static void LogException(Exception ex)
{
//Log my Exception
}