【问题标题】:How to handle exceptions in a multi-layered ASP.NET Web Application如何处理多层 ASP.NET Web 应用程序中的异常
【发布时间】:2012-06-08 17:01:03
【问题描述】:

我有一个带有 UI、Service 层 和 Repository 层 的 ASP.NET Web Forms 应用程序。

我的 服务层 中的一些方法与 Web 服务通信,因此我想将对 Web 方法的所有调用包装在 Try-Catch-Finally 构造中。

假设我的服务层中有以下方法:

public RegistrationDetails GetRegistrationDetails(int userId)

public bool RegisterUser(UserData myUserData)

其中RegistrationDetails 和myUserData 是对象类型(类)。

我的担忧如下:如果我创建一个Try-Catch-Finally 以在上面列出的方法的实现中包装对 Web 服务的调用,如果出现异常,如果返回类型,我如何返回消息字符串是RegistrationDetails 和bool?

我正在考虑为每个返回对象添加一个属性,但我不知道这是否是一个好的解决方案。例如,而不是使用bool:

public class RegisterResponse
{
   public bool isRegistered { get; set; }
   public string ExceptionMessage { get; set; }
}

public RegisterResponse RegisterUser(UserData myUserData)

然后检查 ExceptionMessage 是null 还是String.Empty。这是一个好方法吗?谢谢

【问题讨论】:

  • 我通常让异常冒泡到一个表单并在那里处理它。当您在较低级别捕获特定异常时,您可能会错过介于两者之间的错误的真正原因。在较低的级别,我只是将它们扔掉......
  • 感谢您的回答。我之所以要捕获所有异常,是为了避免用户看到典型的 ASP.NET 错误页面。相反,我想处理它们并向用户(通过 UI)显示最佳信息集,以简化问题解决过程。

标签: asp.net exception-handling multi-layer


【解决方案1】:

1) 正如 IrishChieftain 所说,将异常冒泡到表单中是好的,您将能够更好地响应异常

2) 您还可以将引用参数作为数组来存储方法生成的异常消息

public bool RegisterUser(UserData myUserData, optional ref ArrayList<string> errors)
{
  if(error)
    errors.Add("This error occured")
}

3) 对于 Instance Object,您可以使用 ArrayList 的 Instance 变量来处理错误并将其返回到属性中

public class MyClass
{
   private ArrayList<string> errors = new ArrayList<string>

   public ArrayList<string> ExceptionMessages()
   {
      get 
      {
          return errors;
      }
   }

  public RegistrationDetails GetRegistrationDetails(int userId) { }
}

//Used like this:
MyClass c = new MyClass();
c.GetRegistrationDetails();

if(c.ExceptionMessages > 0)
{
    //output errors
}

但我更喜欢第一种方法 - 像输出格式这样的灵活性

【讨论】:

    【解决方案2】:

    将原始异常从服务传递给您的客户端(Web 表单层)可能会有风险。如果它是数据库异常,它可能会暴露您的数据库的详细信息。恶意用户可能会从他们自己的应用程序中调用您的服务层方法。

    您可以在客户端级别预期两种类型的异常:

    1. 通信异常(连接到服务的问题)
    2. 服务器端错误(数据库问题、用户名不唯一、密码无效……其他业务规则异常)

    第一种类型应该在 web 表单层的 try-catch-finally 中捕获,但第二种应该在服务层中捕获,记录,然后按照您的建议包裹在 RegisterResponse 对象中。但是,除了发送 Exception.Message 之外,您可能会考虑使用预期错误的枚举(使用 ServerError 成员来涵盖其他任何内容。)您还可以将 EventId 添加到响应和日志条目中,以便您可以调查错误。

    public enum RegisterResponseError { NoError = 0, SystemError = 1, 
        UserNameNotUnique, PasswordInvalid, etc.  }
    
    public class RegisterResponse
    {
       public bool isRegistered { get; set; }
       public RegisterResponseError ErrorCode { get; set; }
    }
    

    然后在你的客户端代码中,

    if(myRegisterResponse.ErrorCode == RegisterResponseError.NoError)
       // everything was fine
    else
      // show a suitable error message for ErrorCode and display EventId (if logging)
    

    您可以从您的服务返回一个错误字符串,但最好管理您的网络表单层中的任何内容,以防您以后需要本地化内容或使用 CMS。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-26
      • 1970-01-01
      • 1970-01-01
      • 2010-09-08
      • 1970-01-01
      • 2023-02-10
      • 1970-01-01
      • 2011-01-09
      相关资源
      最近更新 更多