C# 捕获 Global.asax 中的错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10061837/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 12:18:18  来源:igfitidea点击:

Catching errors in Global.asax

c#asp.neterror-handling

提问by Peuge

I have the following in my Global.aspx which is meant for handling errors:

我的 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");
        }
    }
}

This works for the most part, but sometimes does not get into Server.Transfer. For some reason HttpContext.Current.Server is null. I figured out where this happens: when errors occur in a user control and in my business logic classes. Am I missing something here?

这在大多数情况下有效,但有时无法进入 Server.Transfer。由于某种原因 HttpContext.Current.Server 为空。我想出了发生这种情况的地方:当用户控件和我的业务逻辑类中发生错误时。我在这里错过了什么吗?

Thanks

谢谢

回答by Peuge

Application Errors can occur at any time - including when no connection is present.

应用程序错误可能随时发生 - 包括不存在连接时。

For example, if a background thread is processing and causes an exception.

例如,如果后台线程正在处理并导致异常。

回答by Imran Rizvi

Application_Error block can catch exception anytime between application life cycle.

Application_Error 块可以在应用程序生命周期之间的任何时间捕获异常。

Application life cycle is parent of Session life cycle as you can understand there can be many sessions within a single application.

应用程序生命周期是会话生命周期的父级,因为您可以理解单个应用程序中可以有多个会话。

Thus you may have HttpContext.Current null at certain errors occured before creating session or after expiring of sessions.

因此,在创建会话之前或会话到期之后发生某些错误时,您可能会拥有 HttpContext.Current null。

If you want to write session specific error redirects you should check for Null of current HttpContext always.

如果您想编写特定于会话的错误重定向,您应该始终检查当前 HttpContext 的 Null。

You can also use Server.GetLastError to know the error details occured and write your error page redirect through CustomError tag in web.config

您还可以使用 Server.GetLastError 来了解发生的错误详细信息,并通过 web.config 中的 CustomError 标记编写错误页面重定向

See the following link

请参阅以下链接

http://weblogs.asp.net/scottgu/archive/2006/08/12/Tip_2F00_Trick_3A00_-Show-Detailed-Error-Messages-to-Developers.aspx

http://weblogs.asp.net/scottgu/archive/2006/08/12/Tip_2F00_Trick_3A00_-Show-Detailed-Error-Messages-to-Developers.aspx

回答by Fezal halai

enter image description hereBlock Level

在此处输入图片说明块级

This is the most granular level of exception handling in applications. We are very familiar with try-catch blocks that we can wrap over a set of code and if an exception occurs then it will handle this exception. The exception handling block is like this.

这是应用程序中最细粒度的异常处理级别。我们非常熟悉 try-catch 块,我们可以将它们包装在一组代码上,如果发生异常,它将处理此异常。异常处理块是这样的。

try
{
    throw new InsufficientMemoryException();
}
catch (Exception ex)
{
    throw new Exception("");
}
catch
{
    throw;
}

Since this is not a basic exception handling article, we will not go deepper into that example.

由于这不是一篇基本的异常处理文章,我们不会深入研究该示例。

Page Level

页面级别

We can implement an exception handling mechanism at the page level. The advantage is that we do not need to wrap all our code within the try-catch-finally block; we can say that, this is centralizing the exception handling mechanism of a page. Wherever exception bubbles up, it will catch by following code.

我们可以在页面级别实现异常处理机制。优点是我们不需要将所有代码都包装在 try-catch-finally 块中;可以说,这是集中了页面的异常处理机制。只要异常冒泡,它就会通过以下代码捕获。

void Page_Error(object sender, EventArgs e)
{
    Exception ex = Server.GetLastError();
}

To determine the Exception type we need to use the GetLastError() function of the Server class that will return the exception type object and by checking this object we can make further decisions, whether to handle the exception within this page or throw it to a higher level. If a higher level then what higher level?

要确定异常类型,我们需要使用 Server 类的 GetLastError() 函数,该函数将返回异常类型对象,通过检查该对象,我们可以做出进一步的决定,是在此页面内处理异常还是将其抛给更高层等级。如果是更高的级别,那么更高的级别是什么?

Application Level

应用层

Yes, this is the top level of the exception handle mechanism. If we implement it in the Global.asax page. We all are familiar with the Global.asax page that mostly deals with the Global (application) and session related objects. If we implement the Application_Error() event within this page then all unhandled exceptions will stack here and we can make a supreme decision about the error. Whether we will ignore it or log it or send it in mail. Here is the implementation of Application_Error() in a Global.asax page.

是的,这是异常处理机制的顶层。如果我们在 Global.asax 页面中实现它。我们都熟悉 Global.asax 页面,该页面主要处理与全局(应用程序)和会话相关的对象。如果我们在这个页面中实现 Application_Error() 事件,那么所有未处理的异常都会在这里堆积,我们可以对错误做出最高决策。我们是否会忽略它或记录它或通过邮件发送它。这是 Global.asax 页面中 Application_Error() 的实现。

protected void Application_Error(object sender, EventArgs e)
{
    //Catch Exception in Central place
    Exception exceptionObject = Server.GetLastError();
}

The Exception detection mechanism is very similar to the Page Level exception handling mechanism. We are using the GetLastError() function of the Server class that will return one exception type object. Now, it's our duty to investigate the exception type further and the possible solution for it.

异常检测机制与页面级异常处理机制非常相似。我们正在使用 Server 类的 GetLastError() 函数,该函数将返回一个异常类型对象。现在,我们有责任进一步调查异常类型及其可能的解决方案。

Fine, we have seen the three levels of the exception handling mechanism in ASP.NET applications. Now, the obvious question is, shall we implement all those levels in a single application? Why not? They can peacefully adjust themselves within the same application and moreover they work like a team. If one fails to handle an exception then the other tries. If again it fails then its higher authority tries, like this.

很好,我们已经看到了 ASP.NET 应用程序中异常处理机制的三个层次。现在,显而易见的问题是,我们是否应该在单个应用程序中实现所有这些级别?为什么不?他们可以在同一个应用程序中平静地调整自己,而且他们像团队一样工作。如果一个无法处理异常,则另一个尝试。如果它再次失败,那么它的更高权威会尝试,就像这样。

Fine, the next question is if the bottom level is able to solve the exception? Will it call to the higher level? No, if the lower level is capable of handling an exception then it will not bubble up (call) an exception to its higher level. Let's clear up the concept.

好的,下一个问题是底层是否能够解决异常?它会呼唤更高的层次吗?不,如果较低级别能够处理异常,那么它不会冒泡(调用)异常到其较高级别。让我们理清概念。

In one ASP.NET page I have written this code.

在一个 ASP.NET 页面中,我编写了这段代码。

try
{
  throw new DivideByZeroException();
}
catch (DivideByZeroException ex)
{
}
catch
{
    throw;
}

Where we are throwing a DivideByZero Exception from a try block and next to that we are catching it by passing a proper Exception object type. So the catch block can handle the exception. Now make the situation a bit more complex. Within this page we will keep the following code for the global exception handling in the page level.

我们从 try 块中抛出 DivideByZero 异常,然后通过传递适当的异常对象类型来捕获它。所以catch块可以处理异常。现在让情况变得更复杂一些。在这个页面中,我们将在页面级别保留以下用于全局异常处理的代码。

void Page_Error(object sender, EventArgs e)
{
    Exception ex = Server.GetLastError();
}

And we will see that the code will not execute at the time of the exception handling. Because the native try-catch block is sufficient to handle the exception, no need to call its superior mechanism and for the same reason the Application Level exception mechanism will be skipped, if any. Fine, so far we have learned the levels of the exception mechanism and clarified a few concepts of it. We will now implement all those levels in one sample application and we will fulfill our goal. Let's proceed step-by-step.

并且我们会看到代码在异常处理的时候不会执行。因为原生的 try-catch 块足以处理异常,所以不需要调用其上级机制,出于同样的原因,应用级异常机制将被跳过,如果有的话。好的,到此为止我们已经了解了异常机制的层次,并阐明了它的一些概念。我们现在将在一个示例应用程序中实现所有这些级别,我们将实现我们的目标。让我们一步一步来。

Step 1: Create exception in block level and wrap with try-catch

第 1 步:在块级创建异常并用 try-catch 包装

The step is pretty simple and we have done it many times. Within a try block we are throwing an InsufficientMemoryException and we are assuming that this try block will throw “DivideByZeroException” , if our assumption is right then we can handle this exception otherwise we will throw it to a higher level.

这一步非常简单,我们已经做过很多次了。在 try 块中,我们抛出 InsufficientMemoryException 并且我们假设这个 try 块将抛出“DivideByZeroException”,如果我们的假设是正确的,那么我们可以处理这个异常,否则我们将把它抛到更高的级别。

try
{
    throw new InsufficientMemoryException();
}
catch (DivideByZeroException ex)
{
   //show Message
}
catch
{
    throw;
}

Where is the higher level mechanism? The page level. We will implement it in the next step.

上位机制在哪里?页面级别。我们将在下一步中实施它。

Step 2: Implement exception handling mechanism in page level

第二步:在页面层面实现异常处理机制

Here is the next level of exception handling. We have implemented a Page_Error() event that can capture all unhandled exceptions within this page. Now, we are expecting this page to only throw an ObjectDisposeException and a little bit optimistically we have kept the mechanism to handle only this type of exception. (That is a very silly implementation, we should not do that.). Anyway, if the exception is any other type then we will throw it to a higher handling mechanism.

这是异常处理的下一个级别。我们已经实现了一个 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);
}

The next higher authority is the Application Level exception handling mechanism.

下一个更高的权限是应用程序级异常处理机制。

Step 3: Implement Application_Error() in Global.asax page

第 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
}

And the LogException() function is a stub for implementing much more stuff by going beyond our core explanation. Here it is.

LogException() 函数是一个存根,用于通过超出我们的核心解释来实现更多的东西。这里是。

public static void LogException(Exception ex)
{
    //Log my Exception
}