良好的错误处理习惯
对于asp.net网站,什么是好的错误处理方法?例子?谢谢!
解决方案
我发现特别有用的一种做法是创建一个通用错误页面,然后将web.config的customErrors节点上的defaultRedirect设置为该错误页面。
然后设置global.asax以记录所有未处理的异常,然后将它们(未处理的异常)放在某个类的静态属性中(我有一个名为ErrorUtil的类,具有静态LastError属性)。然后,错误页面可以查看此属性,以确定向用户显示的内容。
此处有更多详细信息:http://www.codeproject.com/KB/aspnet/JcGlobalErrorHandling.aspx
与任何.net项目一样,我发现最好的方法是仅捕获特定错误类型(如果可能在给定页面上发生)。
例如,我们可以为给定输入的用户捕获格式异常(以防JavaScript验证失败且我们未使用tryparse),但始终将顶级异常的捕获留给全局错误处理程序。
try { //Code that could error here } catch (FormatException ex) { //Code to tell user of their error //all other errors will be handled //by the global error handler }
我们可以使用ASP.Net的开源elmah(错误记录模块和处理程序)为我们执行此顶级/全局错误捕获。
使用elmah,它可以创建错误日志,该错误日志可通过简单配置的Web界面查看。我们还可以过滤不同类型的错误,并为不同的错误类型设置自己的自定义错误页面。
好吧,这是相当开放的,这完全是很酷的。我将带我们从Dot Net Spider下载的.doc一词,这实际上是我的小公司代码标准的基础。该标准包括一些非常有用的错误处理技巧。
一个这样的例外示例(我不记得这是文档的原始文档还是我们将其添加到文档中):
永远不要执行catch异常,什么也不做。如果隐藏异常,我们将永远不会知道该异常是否发生。我们应该始终通过编程检查所有错误条件来尝试避免异常。
不做什么的示例:
try { ... } catch{}
除非我们有充分的理由,否则这很顽皮。
我们应该确保可以捕获应用程序生成的大多数错误,并向用户显示友好的消息。但是当然,我们无法捕获所有错误,因为可以由另一个用户使用web.config和defaultRedirect。记录错误的另一个非常方便的工具是ELMAH。 ELMAH将记录应用程序生成的所有错误,并以一种易于阅读的方式向我们显示。在应用程序中插入ELMAH就像在web.config文件中添加几行代码并添加程序集一样简单。我们绝对应该尝试一下ELMAH,它将为我们节省数小时的痛苦。
http://code.google.com/p/elmah/
- 在每个页面中针对可能发生的异常进行防御性编码,并进行适当处理,以免每次发生异常时都不会打扰用户。
- 记录所有异常,并提供参考。
- 为任何未处理的异常提供一个通用错误页面,该页面提供了用于支持的参考(支持可以从日志中识别详细信息)。不要显示实际的异常,因为大多数用户不会理解该异常,但是由于它会公开有关我们系统的信息(可能是密码等),因此存在潜在的安全风险。
- 不要捕获所有异常,不要对它们采取任何措施(如上述答案)。这样做几乎没有一个很好的理由,有时我们可能想捕获特定的异常,而不是故意进行任何操作,但是应该明智地使用它。
将用户重定向到标准错误页面并不总是一个好主意。如果用户正在处理表单,则可能不希望将其重定向到正在处理的表单之外。我将所有可能导致异常的代码放入try / catch块中,并在catch块中吐出一条警告消息,警告用户已发生错误,并将异常记录在数据库中,包括表单输入,查询字符串,等等。我正在开发内部网站,因此,大多数用户在遇到问题时都只给我打电话。对于公共站点,我们可能希望使用类似elmah的东西。
我应该尝试阻止所有内容吗?有时我不想捕获任何特定的东西,无论如何都会通过层次结构中更高级别的方法捕获错误。
如果这是主要方法,那么子方法的最佳实践是什么?
private void mainMethod() { try { subMethod(); } catch { //do something } }
这:
private void subMethod() { try{ //code //code } catch { throw; } }
或者这个:
private void subMethod() { //code //code }
public string BookLesson(Customer_Info oCustomerInfo, CustLessonBook_Info oCustLessonBookInfo) { string authenticationID = string.Empty; int customerID = 0; string message = string.Empty; DA_Customer oDACustomer = new DA_Customer(); using (TransactionScope scope = new TransactionScope()) { if (oDACustomer.ValidateCustomerLoginName(oCustomerInfo.CustId, oCustomerInfo.CustLoginName) == "Y") { // if a new student if (oCustomerInfo.CustId == 0) { oCustomerInfo.CustPassword = General.GeneratePassword(6, 8); oCustomerInfo.CustPassword = new DA_InternalUser().GetPassword(oCustomerInfo.CustPassword, false); authenticationID = oDACustomer.Register(oCustomerInfo, ref customerID); oCustLessonBookInfo.CustId = customerID; } else // if existing student { oCustomerInfo.UpdatedByCustomer = "Y"; authenticationID = oDACustomer.CustomerUpdateProfile(oCustomerInfo); } message = authenticationID; // insert lesson booking details new DA_Lesson().BookLesson(oCustLessonBookInfo); } else { message = "login exists"; } scope.Complete(); return message; } }