如何:处理异常,最佳实践

时间:2010-05-29 10:11:50

标签: c# asp.net exception exception-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();
        }

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

最佳做法是什么?

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

如果发生异常该怎么办?

在这个例子中

: 这是一个用户登录,所以即使一切都失败了,用户也应该得到一些有意义的信息 - 按行:登录确定(只是重定向),登录不正常(用户名/密码错误),登录不可能由于内部问题,抱歉(发生例外)。

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

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

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

3 个答案:

答案 0 :(得分:4)

两条黄金法则:

  1. 如果某个方法无法按照其名称所做的操作,则抛出异常。
  2. 除非您确切知道如何处理异常,否则不要捕获异常。
  3. 请记住,异常表示出现了问题,而某些特定内容可能不是您的想法。 (内存不足,堆栈溢出,第三方服务中断,部署错误导致组件丢失,配置错误,安全异常等)。

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

    以下是一些您可能感兴趣的链接:

答案 1 :(得分:3)

  

您的图书馆代码或代码   在你的高层使用   应用程序必须始终只抛出   例外,从不担心如何   处理它们。

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

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

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

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

  

我强烈建议不要这样做   处理所有问题的一般做法   全局Application_Error中的异常。

答案 2 :(得分:3)

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

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

将此方法的概念用作合同可以让您做出正确的决定。如果方法契约登录到数据库或某些数据库操作,那么允许异常传播可能是有意义的。

具体:使用第一个例子:

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上设置内部异常:

        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,因为您无法通知用户。所以你可以让它传播到你可以用它做某事的水平。

希望有所帮助!