如何:处理exception,最佳实践

需要实现全局error handling,所以也许您可以帮助以下示例…

我有这个代码:

public bool IsUserAuthorizedToSignIn(string userEMailAddress, string userPassword) { // get MD5 hash for use in the LINQ query string passwordSaltedHash = this.PasswordSaltedHash(userEMailAddress, userPassword); // check for email / password / validity using (UserManagementDataContext context = new UserManagementDataContext()) { var users = from u in context.Users where u.UserEMailAdresses.Any(e => e.EMailAddress == userEMailAddress) && u.UserPasswords.Any(p => p.PasswordSaltedHash == passwordSaltedHash) && u.IsActive == true select u; // true if user found return (users.Count() == 1) ? true : false; } } 

和md5一样:

 private string PasswordSaltedHash(string userEMailAddress, string userPassword) { MD5 hasher = MD5.Create(); byte[] data = hasher.ComputeHash(Encoding.Default.GetBytes(userPassword + userEMailAddress)); StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < data.Length; i++) { stringBuilder.Append(data[i].ToString("x2")); } Trace.WriteLine(String.Empty); Trace.WriteLine("hash: " + stringBuilder.ToString()); return stringBuilder.ToString(); } 

那么,我将如何处理这些函数的exception? 它们首先从Default.aspx页面调用。 第二个只从类库中的其他函数调用。

什么是最佳做法?

  • 环绕代码INSIDE每个函数都有try-catch
  • try-catch包围FUNCTION CALL
  • 别的什么?

exception发生时该怎么办?

在这个例子中:这是一个用户登录,所以即使一切都失败,用户也应该得到一些有意义的信息 – 沿着这样的行:登录ok(只是重定向),登录不正常(用户名/密码错误),由于内部问题而无法登录,抱歉(发生exception)。

对于第一个函数我担心如果数据库访问有问题。 不确定是否有任何需要在第二个处理。

thnx的信息。 你会怎么做? 需要具体的信息(我更容易理解),还有关于如何处理其他任务/function的一般信息。

我环顾了互联网,但是每个人都有不同的想法,所以不确定该做什么…会选择大多数选票,或大多数逻辑解释答案:)谢谢。

您的库代码或应用程序中较高层使用的代码必须始终只抛出exception,而不必担心如何处理它们。

这很重要,因为您可以在许多地方使用此库以用于不同目的。

在您的应用程序表示层中,如果您正在使用库代码并且您知道可能的exception,那么请使用try / catch捕获它们。

由于您使用的是asp.net,我建议您编写一个通用的基于页面的类,并在Page_Error事件中使用一些error handling机制来捕获页面上所有未处理的exception。

除此之外,即使在global.asax中也可以使用Application_Error来捕获应用程序的任何部分,模块,处理程序,服务,页面等中的任何未处理的exception。

我强烈建议不要在全局Application_Error中处理所有exception。

两条黄金法则:

  1. 如果某个方法无法按照其名称所做的操作,则抛出exception。
  2. 除非您确切知道如何处理exception,否则不要捕获exception。

请记住,一个例外表明某些事情出了问题,而且某些事情可能与您的想法不符。 (内存不足,堆栈溢出,第三方服务中断,部署拙劣导致组件丢失,配置错误,安全exception等)。

除了极少数例外,您应该看到Pokemonexception处理的唯一位置是代码的最顶层,exception应该在某处发布。 例如,在global.asax文件中的Application_Error方法中。

以下是一些您可能会觉得有帮助的链接:

  • 如果你的方法不能做它的名字所能承诺它可以,扔
  • exception处理的两个黄金法则
  • exception驱动的开发
  • ELMAH – ASP.NET的错误记录模块和处理程序

您需要考虑方法定义的合同。 如果某个方法无法履行其合同,那么您需要一个例外。 方法中抛出的exception应该转换为从方法合同的角度来看有意义的exception。

在第一种情况下,我会捕获任何可以由语句执行引发的exception(例如数据库错误)并将它们转换为类似AuthorizationException的内容。 从方法契约的角度来看,允许exception直接传播是没有意义的。 例如,当方法履行作者是否被授权的合同时,允许数据库exception从方法中逃脱是没有意义的。

将这种方法的概念作为契约使您可以做出正确的决定。 如果方法契约正在登录数据库或某些数据库操作,那么允许exception传播可能是有意义的。

具体:使用第一个例子:

 public bool IsUserAuthorizedToSignIn(string userEMailAddress, string userPassword) { try { // get MD5 hash for use in the LINQ query string passwordSaltedHash = this.PasswordSaltedHash(userEMailAddress, userPassword); // check for email / password / validity using (UserManagementDataContext context = new UserManagementDataContext()) { var users = from u in context.Users where u.UserEMailAdresses.Any(e => e.EMailAddress == userEMailAddress) && u.UserPasswords.Any(p => p.PasswordSaltedHash == passwordSaltedHash) && u.IsActive == true select u; // true if user found return (users.Count() == 1) ? true : false; } } catch(ThisException e) { thrown new AuthorisationException("Problem1 occurred"); } catch(ThatException e) { thrown new AuthorisationException("Problem2 occurred"); } catch(OtherException e) { thrown new AuthorisationException("Problem3 occurred"); } } 

您可能还想在AuthorisationException上设置内部exception:

  catch(ThisException e) { thrown new AuthorisationException("Problem1 occurred", e); } 

然后您的客户端代码可以这样做:

 try { if(User.IsUserAuthorizedToSignIn) { // Let the magic happen } else { // No rights } } catch(AuthorisationException e) { // Let the user know there is something up with the system. } 

您可能决定不想在即时呼叫站点捕获AuthorisationException,因为您无法通知用户。 所以你可以让它传播到你可以用它做某事的水平。

希望有所帮助!