Vb.net ASP.NET中显示异常消息的递归方法

Vb.net ASP.NET中显示异常消息的递归方法,vb.net,exception,recursion,messages,Vb.net,Exception,Recursion,Messages,我已经开始大量使用异常,我相信我会从中成长出来,以一种艰难的方式学习优缺点,但在我成为异常大师之前,我想知道这种技术是否可以接受 我打算将数据库异常包装在我自己的“SorryFailedToSaveYourData”异常中,然后在异常中递归移动,显示消息,有点像这样: Try DoSomeWork Catch BuildErrorMessage(lblError,ex) End Try Public Sub BuildErrorMessage(ByVal lbl As Labe

我已经开始大量使用异常,我相信我会从中成长出来,以一种艰难的方式学习优缺点,但在我成为异常大师之前,我想知道这种技术是否可以接受

我打算将数据库异常包装在我自己的“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
试试看
DoSomeWork
抓住
BuildErrorMessage(lblError,ex)
结束尝试
公共子构建错误消息(ByVal lbl作为标签,ByVal ex作为例外)
lbl.Text+=“
”和ex.消息 而不是ex.InnerException什么都不是 BuildErrorMessage(lbl,例如InnerException) 结束时 端接头
这种做法有用吗?或者说,在处理异常时,我完全错过了机会?我知道您可以创建自己的异常,但对于我们正在进行的项目的规模来说,这似乎有些过头了


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

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

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


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

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

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

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

例如,如果您知道用户将从家中连接,但无法保证会有Internet连接,则可以检查Internet连接并显示一条消息,说明用户需要连接,而不是仅尝试使用Internet连接,如果不存在,则创建异常。

编辑 我一开始误解了你的问题,如果你向最终用户显示信息,你可能不想这样做。如果您要记录异常以便对后者进行故障排除,您将希望执行我建议的操作

====

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

尽管您的实际代码中有一个错误,但您很可能会在无限循环中结束,因为您的外部异常将始终有一个内部异常

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
公共子构建错误消息(ByVal lbl作为标签,ByVal ex作为例外)
lbl.Text+=“
”和ex.消息 如果不是ex.InnerException,则什么都不是 BuildErrorMessage(lbl,例如InnerException) 如果结束 端接头
编辑 我一开始误解了您的问题,如果您向最终用户显示信息,您可能不想这样做。如果您要记录异常以便对后者进行故障排除,您将希望执行我的建议

====

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

尽管您的实际代码中有一个错误,但您很可能会在无限循环中结束,因为您的外部异常将始终有一个内部异常

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
公共子构建错误消息(ByVal lbl作为标签,ByVal ex作为例外)
lbl.Text+=“
”和ex.消息 如果不是ex.InnerException,则什么都不是 BuildErrorMessage(lbl,例如InnerException) 如果结束 端接头
ex.ToString()将生成格式化的异常文本,您应该使用该文本而不是.Message,因为它可能不会提供调试所需的全部信息

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

StringBuilder.ToString().Replace(Environment.NewLine, "<br />")
StringBuilder.ToString().Replace(Environment.NewLine,
ex.ToString()将生成格式化的异常文本,您应该使用该文本而不是.Message,因为它可能不会提供调试所需的全部信息