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

2024-04-20

使用 .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同时尝试结束响应流。这是唯一不能捕获和忽略的异常类型。咕噜!谁能告诉我:

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

编辑 - 更多上下文

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

事实上,目前的代码似乎运行良好。但是,在某些情况下,希望在 Web 应用程序代码中具有显式的 catch 块来直接调用异常处理策略。这种情况是不能正常工作的。我想要一个可以在所有可能的调用方法下工作的解决方案。我确实有这样的印象:如果不涉及 EHAB,事情会简单得多,但不幸的是,它在我们所有的代码中都使用,并且提供了许多其他好处,我宁愿保留它。

编辑 - 测试结果

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

  1. 写入当前页面HttpResponse直接地。
  2. 构造异常对象并调用ExceptionPolicy.HandleException(ex, "Top Level")直接地。
  3. 抛出异常对象,捕获它并调用ExceptionPolicy.HandleException(ex, "Top Level")在 catch 块中。
  4. 抛出一个异常对象并让Page_Error事件调用ExceptionPolicy.HandleException(ex, "Top Level").
  5. 抛出一个异常对象并让Application_Error事件调用ExceptionPolicy.HandleException(ex, "Top Level").
  6. 抛出异常对象并让我的自定义IHttpModule班级电话ExceptionPolicy.HandleException(ex, "Top Level").

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

  • 方法 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 twice.

每种方法的测试结果HttpContext.Current.Response.End被称为,但包裹在try ... catch block:

  • 方法 5、6 - 错误页面标记替换了测试页面标记(所需结果)。
  • 方法 1、3、4 - 错误页面标记替换了测试页面标记,但 ASP.NET 抛出ThreadAbortException它被捕获块捕获并吸收。
  • 方法 2 - 错误页面标记替换了测试页面标记,但我得到了ThreadAbortException and also two ExceptionHandlingExceptions.

这是一系列可笑的行为。 :-(


看一下ELMAH http://code.google.com/p/elmah/.
ELMAH 上有很多文章和操作方法,只需 google 或 bing 就可以找到:-)

优点
+ 它记录几乎所有内容
+ 电子邮件通知
+ 远程查看错误

我建议使用它并重定向到默认错误页面,正如 Ariel 提到的那样。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

异常处理 在 ASP.NET 中运行的应用程序块异常处理程序无法调用 Response.End() 的相关文章

  • 将 MyGeneration 与 Fluent NHibernate 结合使用

    我在这里找到了一个使用 MyGeneration 生成 NHibernate 代码的绝佳模板 http vucetica blogspot com 2009 01 nhibernate template for my Generation
  • 为什么 C++11/Boost `unordered_map` 在擦除时不重新散列?

    我想知道为什么 C 11 和 Boost 的 hashmap 在通过迭代擦除元素时不会调整大小 即使这在技术上不是内存泄漏 我认为这可能是应用程序中的一个严重问题 这对我来说是一个隐藏的问题 很难追踪它 并且它实际上可能会影响许多应用程序
  • 将 CryptoStream 解密为 MemoryStream

    我编写了一个过程 其中文件被加密并上传到 Azure 然后必须解密下载过程 这会失败并出现 填充无效且无法删除 错误 或 要解密的数据长度为无效的 错误 我在网上尝试了很多解决方案 包括C 使用 RijndaelManaged 和 Cryp
  • 以 ASCII 字符串形式获取 MemoryStream 内容的快速方法

    我在 MemoryStream 中有一个 JSON 字符串 我使用以下代码将其作为 ASCII 字符串获取 MemoryStream memstream new MemoryStream Write a JSON string to mem
  • 在 C++ 中重用异常处理代码

    我有这两个函数 具有重复的异常处理 其唯一目的是显示错误消息 void func1 noexcept try do task do another task catch const std out of range e show msg O
  • 在 Asp.net Web API 中处理 CORS 预检

    我的架构中有三个应用程序 它们位于同一服务器上 但具有不同的端口号 A Token Application port 4444 Asp net WebApi B API Application port 3333 Asp net WebAp
  • C# 中的异步方法如何工作?

    我在我的一些项目中使用异步方法 我喜欢它 因为它使我的应用程序更具可扩展性 但是 我想知道异步方法如何在后台真正工作 NET 或 Windows 如何知道调用已完成 根据我进行的异步调用的数量 我可以看到创建了新线程 但并不总是 为什么 此
  • 如何存储生成的格式化 C 字符串

    这是一个新手问题 为了创建格式化的 C 字符串 我使用printf like int n 10 printf My number is i 10 但是 怎么样 int n 10 char msg My number is i 10 prin
  • 使用 .NET Core Razor Pages 将文件下载到浏览器

    使用 ASP NET Razor Pages 我尝试将文件下载到浏览器 在页面 html 中 使用这样的链接效果很好 href DownloadableFiles testB csv download newname gt Download
  • 如何在 .NET 6.0 中使用最小 Api 配置 Newtonsoft Json

    I have net6 0具有最少 api 的项目 我想使用NetwtonsoftJson而不是内置的System Text Json用于序列化和反序列化的库 目前我有这个配置JsonOptions并且按预期工作 builder Servi
  • FireFox 中的默认表单按钮

    我正在构建一个服务器控件 它将搜索我们的数据库并返回结果 服务器控件包含一个 ASP Panel 我已将面板上的默认按钮设置为等于我的按钮 id 并将表单默认按钮设置为等于我的按钮 id 在面板上 MyPanel DefaultButton
  • 更改子进程中的 iostream

    现在 我正在开发一个项目 其中我需要启动一个子进程来使用 C 在 Linux 中执行一个新程序 并且我需要重定向标准输入和输出 就像在 C 中一样 它们是cin and cout 到一个文件 这意味着在子进程中 标准输入和输出都是文件 子进
  • 关于 MEF 战略和结构的问题

    我的任务是模块化一个 C 应用程序 该应用程序是一个非常大的 Delphi 应用程序的重写 数据库有 249 个表 业务限制禁止对 NET 进行彻底的重新设计和更好的整体架构 因此我们基本上只是用 C 逐步重写 Delphi 应用程序的模块
  • C# SerialPort BaseStream ReadAsync - CancellationToken 从未取消?

    我尝试以异步方式从串行端口读取数据 请记住操作所花费的时间不得超过指定的时间段 我使用的代码 private async Task
  • 如何将 typedef 结构传递给函数?

    此刻我正在努力 void avg everything 但这给了我错误 error subscripted value is neither array nor pointer 当我今天早些时候收到此错误时 这是 因为我没有正确地将 2D
  • GridView,在代码中添加标题行第 2 部分

    这是这篇文章的延续 但添加了完整的代码 ASP NET GridView 在代码中添加标题行 https stackoverflow com questions 19119004 asp net gridview adding header
  • Web 服务无法使用 GAC 中的类型创建类型错误

    遇到一个不寻常的问题时 我似乎喜欢做一些不常见的事情 我有一个复合控件 它检查给定的 Web 服务文件是否存在于我的应用程序的根目录中 如果不存在 它会在标记中创建带有必要指令的文件以进行滚动 如下所示 反过来 它被保存到输出中 完成此步骤
  • 有C语言的解释器吗? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话
  • 如何在 C++ 中打印变量的名称? [复制]

    这个问题在这里已经有答案了 可能的重复 在C中获取变量名称的编程方法 https stackoverflow com questions 1623111 programmatic way to get variable name in c
  • XslCompiledTransform 和自定义 XmlUrlResolver:“具有相同键的条目已存在”

    有没有办法调试由自定义 XmlUrlResolver 从数据库加载的 XSLT 文档 或者有人知道下面的错误消息是关于什么的吗 我有一个导入通用 xslt 文档的 XSLT 样式表

随机推荐