使用.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所说.