.NET Web应用程序中的异常处理
我承认:我不必过多地处理异常。我知道我应该做更多的事情,但是我永远无法把头从哪里开始和从哪里停止。我不懒。离得很远。这是因为我对异常处理的模棱两可感到不知所措。似乎即使在最小的应用程序中,似乎也可以存在无数个可以应用异常处理的地方,并且开始感觉像是过分杀伤。
我经过仔细的测试,验证和默默的祈祷,但这是等待发生的严重编程事故。
那么,异常处理最佳实践是什么?尤其是在哪里应该应用异常处理的最明显/最关键的地方,以及应该在何处考虑进行异常处理的地方?
很抱歉这个问题含糊不清,但我真的想一劳永逸地结束这本书。
解决方案
回答
微软的模式与实践团队做得很好,将异常管理的最佳实践整合到了企业库异常处理应用程序块中
如果不使用企业库,我强烈建议我们阅读他们的文档。 P&P团队介绍了异常处理的常见方案和最佳实践。
为了让我们入门,我建议阅读以下文章:
- MSDN上的异常处理
- MSDN上.NET中的异常管理
- .NET在CodeProject上的异常处理最佳实践
ASP.NET特定文章:
- 用户友好的ASP.NET异常处理
- 使用ASP.NET进行全局异常处理
- C#和ASP .Net中的异常处理
回答
在最基本的级别上,我们应该处理Global.asax文件中的HttpApplication.Error事件。这应该将发生的任何异常记录到一个地方,以便我们可以查看异常的堆栈跟踪。
除了此基本级别之外,理想情况下,我们还应该处理可以从异常中恢复的异常,例如,如果我们期望文件可能被锁定,则处理IOException并将错误报告给用户将是一个好主意。
回答
我建议我们从添加一个良好的错误页面开始,该页面可以捕获所有异常并向用户显示不太友好的消息。确保记录所有可用的异常详细信息并进行修改。让用户知道我们已完成此操作,并给他一个链接,该链接指向可以(可能)正常工作的页面。
现在,使用该日志来检测应在何处进行特殊异常处理。请记住,除非我们打算对异常进行处理,否则捕获异常是没有用的。如果我们具有上述页面,则除非在该特定点有某种特定的恢复方法,否则在所有数据库操作上单独捕获数据库异常都没有用。
请记住:比不捕获异常更糟糕的是,捕获异常并且什么也不做。这只会隐藏真正的问题。
回答
异常处理的黄金法则是:
"Only catch what you know how to handle"
我看过太多try-catch块,其中catch除了重新抛出异常外什么也不做。这没有任何价值。仅仅因为我们调用了可能引发异常的方法,并不意味着我们必须在调用代码中处理可能的异常。让异常沿调用堆栈传播到其他知道该怎么做的代码通常是完全可以接受的。
在某些情况下,让异常一直传播到用户界面层然后捕获并向用户显示消息是有效的。可能是没有代码最适合知道如何处理这种情况,因此用户必须决定采取的措施。
回答
一般而言,异常处理可能比特定于ASP.NET的更多,但:
- 尝试捕获尽可能接近原因的异常,以便我们可以记录(记录)尽可能多的有关异常的信息。
- 在程序的入口点包括某种形式的全部捕获,最后使用的异常处理程序。在ASP.NET中,这可能是应用程序级错误处理程序。
- 如果我们不知道如何"正确"处理异常,请让它冒泡到捕获所有处理程序,我们可以在其中将其视为"意外"异常。
- 在.NET中使用Try *****方法进行诸如访问词典之类的事情。如果我们在一个循环中抛出多个异常,则可以帮助避免主要的性能问题(异常处理相对较慢)。
- 不要使用异常处理来控制程序的常规逻辑,例如通过throw语句退出循环。
回答
首先使用全局异常处理程序,例如http://code.google.com/p/elmah/。
然后,问题归结为我们在编写哪种应用程序以及需要提供什么样的用户体验。用户体验越丰富,我们将要提供的异常处理就越好。
例如,考虑一个具有磁盘配额,文件大小限制,图像尺寸限制等的照片托管站点。对于每个错误,我们都可以简单地返回"发生了一个错误。请重试"。或者,我们可以进行详细的错误处理:
- "文件很大。最大文件大小为5mb。"
- "图像太大。最大尺寸为1200x1200。"
- "相册已满。最大存储容量为1gb"。
- "我们上传的文件有误。我们的熟客不高兴。请稍后再回来。"
等等等
没有一种适合所有情况的大小。