【问题标题】:A recursive way to display Exception Messages in ASP.NET在 ASP.NET 中显示异常消息的递归方式
【发布时间】:2010-10-02 11:03:56
【问题描述】:

我已经开始大量使用异常,我相信我会从它中成长,因为我会通过艰苦的方式学习优缺点,但是直到我成为异常专家我想知道如果这种技术是可以接受的。

我打算在我自己的“SorryFailedToSaveYourData”异常中包装一个数据库异常,然后递归地移动显示消息的异常,有点像这样:

Try
    DoSomeWork
Catch
    BuildErrorMessage(lblError,ex)
End Try

Public Sub BuildErrorMessage(ByVal lbl As Label, ByVal ex As Exception)
    lbl.Text += "<br />" & ex.Message
    While Not ex.InnerException Is Nothing
        BuildErrorMessage(lbl, ex.InnerException)
    End While
End Sub

这种做法有用吗,还是我在处理异常时完全错过了这条船?我知道您可以创建自己的例外,但对于我们正在处理的项目的规模来说,这似乎有点过头了。

谢谢

【问题讨论】:

    标签: vb.net exception recursion messages


    【解决方案1】:

    我不会向您的应用程序用户显示每条内部异常消息。我会捕获真正的异常(即 SqlException)并将其作为您自己的异常重新抛出(即 throw new YouCantSaveThisTwiceException("This customer ID already exists") )。然后只需在漂亮的显示屏上向用户显示该手写信息即可。向自己发送一封包含完整堆栈跟踪的电子邮件/日志文件/等。

    这有两个目的:

    1) 您可以看到真正的堆栈跟踪,这使您更容易找到并解决问题。

    2) 不必向用户显示可怕的堆栈跟踪。相反,他们阅读了您写的一条好消息,向他们保证,尽管存在问题,但他们并没有“破坏”应用程序。

    这适用于您不希望用户能够通过不同输入修复的异常。对于验证用户输入的异常,您通常可以在表示层中捕获这些异常,并将您的好消息显示在标签上,而无需离开表单。

    只有(仅!!!)如果您确切地知道您将要捕获什么并且您向用户提供有关如何修复它的明确说明,请使用此技术。否则,你最终会两全其美。用户不知道该怎么做,您也不会被告知存在错误。永远不要仅仅为了“捕获所有”异常而将整个方法包装在 try-catch 中。这种类型的处理应该在应用程序级别全局完成。

    我在 Global.asax 中的 application_error 处理程序方法中执行所有全局异常处理(电子邮件、日志记录等)。您还可以创建一个处理应用程序错误的 HttpModule。然后,您可以在项目之间携带该功能。

    【讨论】:

      【解决方案2】:

      ex.ToString() 将生成格式化的异常文本,您应该使用它而不是 .Message,因为它可能无法为您提供调试所需的完整信息。

      我还建议使用 AppendLine() 将字符串构建器传递给递归而不是标签,这样您还可以使用该文本发送电子邮件通知、编写事件查看器以及日志文件。为了在你的 UI 中显示(看起来你想要 html),只需将标签文本值设置为

      StringBuilder.ToString().Replace(Environment.NewLine, "<br />")
      

      【讨论】:

        【解决方案3】:

        您正在异常内部构建标签,大概是因为您想向用户显示消息。如果您的异常跨越应用程序的多个层(您提到包装自己的数据异常),那么这是一个糟糕的主意,因为它会违反封装并强制您的异常处理使用 UI 元素。

        但是,通常,您不希望向用户显示错误消息。用户关心堆栈溢出发生了什么?他只关心应用程序是否损坏以及是否已记录错误报告并将其发送给相应的团队。

        通常,当且仅当应用程序处于无法再运行的状态时,您才希望出现异常。如果它只是有条件地发生,您将希望使用条件显式处理它以检查它,而不是使用异常机制。

        例如,如果您知道用户将在家中进行连接,并且您不能保证一定会有 Internet 连接,则您检查 Internet 连接并显示一条消息说用户需要连接,而不是仅仅尝试使用 Internet连接,如果不存在则创建异常。

        【讨论】:

          【解决方案4】:

          编辑

          起初我误读了您的问题,如果您向最终用户显示信息,您可能不想这样做。如果您要记录异常以便稍后进行故障排除,您将需要按照我的建议进行操作。

          ====

          这是标准的,尽管我也会捕获堆栈跟踪和 Data 属性中的任何项目(虽然我没有看到任何框架代码使用这个你永远不知道的,如果你要抛出自己的异常或重新抛出异常,它很有用.

          虽然您的实际代码中存在错误,但您可能最终会陷入无限循环,因为您的外部异常总是有一个内部异常。

          Public Sub BuildErrorMessage(ByVal lbl As Label, ByVal ex As Exception)   
           lbl.Text += "<br />" & ex.Message    
           If Not ex.InnerException Is Nothing     Then
              BuildErrorMessage(lbl, ex.InnerException)    
            End If 
          End Sub
          

          【讨论】:

            猜你喜欢
            • 2019-09-18
            • 1970-01-01
            • 1970-01-01
            • 2018-03-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多