c# – 异常处理应用程序块异常在ASP.NET中运行的处理程序无法调用Response.End()

使用.NET 3.5,ASP.NET,Enterprise Library 4.1异常处理和日志块,我编写了一个自定义异常处理程序来显示标准错误页面,如下所示:

[ConfigurationElementType(typeof(CustomHandlerData))]
public class PageExceptionHandler : IExceptionHandler {

    public PageExceptionHandler(NameValueCollection ignore) {
    }

    public Exception HandleException(Exception ex, Guid handlingInstanceID) {

        HttpResponse response = HttpContext.Current.Response;
        response.Clear();
        response.ContentEncoding = Encoding.UTF8;
        response.ContentType = "text/html";
        response.Write(BuildErrorPage(ex, handlingInstanceID));
        response.Flush();
        //response.End(); // SOMETIMES DOES NOT WORK

        return ex;
    }
}

这是从这样的异常处理策略调用的:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="exceptionHandling" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Configuration.ExceptionHandlingSettings, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  </configSections>
  <exceptionHandling>
    <exceptionPolicies>
      <add name="Top Level">
        <exceptionTypes>
          <add type="System.Exception, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
            postHandlingAction="None" name="Exception">
            <exceptionHandlers>
              <add logCategory="General" eventId="0" severity="Error" title="Application Error"
                formatterType="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.TextExceptionFormatter, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                priority="0" useDefaultLogger="false" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                name="Log Full Details" />
              <add type="PageExceptionHandler, Test, Culture=neutral, PublicKeyToken=null"
                name="Display Error Page" />
            </exceptionHandlers>
          </add>
        </exceptionTypes>
      </add>
    </exceptionPolicies>
  </exceptionHandling>
</configuration>

这一切都运行正常,除了错误页面被合并到错误发生时显示的任何标记.我认为将response.End()添加到异常处理程序中可以解决这个问题.它确实如此,但我观察到,有时,ASP.NET在尝试结束响应流时抛出ThreadAbortException.这是唯一无法捕获和忽略的异常类型.哎呀!谁能告诉我:

>在什么条件下,ASP.NET在尝试结束响应流时会抛出ThreadAbortException?
>我可以使用更安全的response.End()替代方案吗?
>如果没有,有没有办法在调用response.End()之前检测响应流是否“可以结束”?

编辑 – 更多背景

此代码的设计目标是尽可能简单地将EHAB样式的错误处理添加到Web应用程序.我有一个必须添加到web.config文件的自定义IHttpModule.在模块的Application_Error事件中,它调用ExceptionPolicy.HandleException.必须配置异常处理策略以调用上述的PageExceptionHandler类.整个过程仅涉及少量XML配置,没有额外文件,并且在消费Web应用程序中没有额外的代码行.

实际上,现在的代码似乎工作正常.但是,在某些情况下,需要在Web应用程序代码中具有直接调用异常处理策略的显式catch块.这种情况是不能正常工作的.我想要一个可以在所有可能的调用方法下工作的解决方案.我确实得到的印象是,如果没有参与EHAB会更简单,但不幸的是它在我们所有的代码中使用,并提供了许多其他好处,我宁愿保留它.

编辑 – 测试结果

我创建了一个测试工具,以六种不同的方式练习代码:

>直接写入当前页面的HttpResponse.
>构造一个异常对象并直接调用ExceptionPolicy.HandleException(ex,“Top Level”).
>抛出异常对象,捕获它,并在catch块中调用ExceptionPolicy.HandleException(例如,“顶级”).
>抛出异常对象并让Page_Error事件调用ExceptionPolicy.HandleException(例如,“顶级”).
>抛出异常对象并让Application_Error事件调用ExceptionPolicy.HandleException(例如,“顶级”).
>抛出异常对象并让我的自定义IHttpModule类调用ExceptionPolicy.HandleException(例如,“顶级”).

在编写错误页面标记后,每个方法的测试结果都没有代码来终止响应:

>方法1,2,3 – 错误页面标记与测试页面标记相结合.
>方法4,5,6 – 错误页面标记替换了测试页面标记(所需结果).

调用HttpContext.Current.ApplicationInstance.CompleteRequest时测试每个方法的结果:

>方法1,2,3 – 错误页面标记与测试页面标记相结合.
>方法4,5,6 – 错误页面标记替换了测试页面标记(所需结果).

调用HttpContext.Current.Response.End时测试每个方法的结果:

>方法1,5,6 – 错误页面标记替换了测试页面标记(所需结果).
>方法2,3,4 – 错误页面标记替换了测试页面标记,但EHAB抛出两次ExceptionHandlingException.

调用HttpContext.Current.Response.End时每个方法的测试结果,但包含在try … catch块中:

>方法5,6 – 错误页面标记替换了测试页面标记(所需结果).
>方法1,3,4 – 错误页面标记替换了测试页面标记,但ASP.NET抛出了一个ThreadAbortException,它被catch块捕获并吸收.
>方法2 – 错误页面标记取代了测试页面标记,但我得到了一个
ThreadAbortException以及两个ExceptionHandlingExceptions.

这是一组荒谬的行为. 🙁

最佳答案 看看
ELMAH.

ELMAH上有很多文章和操作方法,只是google或bing for it 🙂

好处
  它几乎记录了一切
  电子邮件通知
  远程查看错误

我建议使用它并重定向到默认错误页面,正如Ariel所说.

点赞