【问题标题】:Best practicies global result - error handling in Asp.Net core 3 and Angular 9最佳实践全局结果 - Asp.Net core 3 和 Angular 9 中的错误处理
【发布时间】:2020-09-10 16:11:13
【问题描述】:

根据微软的建议,程序的正常逻辑不应该使用投掷和抓捕。 Minimize exceptions

作为 ASP.Net 核心清洁架构项目的一部分(具有 3 层通用存储库 - BL 服务 - 控制器),应该如何设计和实现错误处理和结果? 是否应该为所有 Api 控制器和 BL 服务使用结构或全局结果类? 如果将错误和结果封装在一个结构中就足够了吗?

WebApi 项目中的结果类示例:

public class ExampleResult<T> 
{
      public ExampleResult(T value, string message, bool success)
      {
         (...)
      } 
}

控制器:

public ActionResult<ExampleResult<NewResourceDto>> Post([FromBody] NewResourceDto myNewResource)
{
    try
    {
         if(!Validate(myNewResource))
             return new ExampleResult(null, "some business logic validate failed", true);

        ExampleResult result = _service.TrySaveMyNewResource(myNewResource);
        return result;
    }
    catch (Exception ex)
    {
        // Log the exception here...
        return new ExampleResult(null, "some message" + ex, false);
    }
}

然后,Angular 客户端会验证该值是否为 null 和/或成功是真还是假。 该消息包含错误消息。 http状态将为200(无论成功与否)。

如何优雅地最小化异常?

【问题讨论】:

    标签: c# angular asp.net-core error-handling asp.net-core-webapi


    【解决方案1】:

    我同意不应将抛出异常用作系统中的信号。也许我不明白您关于返回结构或全局结果类的问题。似乎是个坏主意。特别是,如果出现问题,请不要返回 HTTP OK 200。

    • 让您的 Web API 控制器尽可能精简和笨拙
    • 将您的 Web API 控制器方法方法包装在一个 try-catch 中,这样您总是在出现意外错误时返回 HTTP 内部服务器错误 500

    控制器方法示例:

    public IActionResult Post([FromBody] NewResourceDto myNewResource)
    {
        try
        {
            _service.TrySaveMyNewResource(myNewResource);
    
            return StatusCode(201);
        }
        catch (Exception ex)
        {
            // Log the exception here...
            return StatusCode(500);
        }
    }
    

    【讨论】:

    • 感谢您的回答。我调整了我的问题(见上文)。我想要返回消息和结果,而不仅仅是 http 状态。
    【解决方案2】:
    • 针对 .Net Core 或任何其他框架中的最佳实践,您需要返回所有 api 的通用模型,该模型包含从 api 返回的所有日期,以防万一它是结果或错误,然后在您的角度服务中您应该检查返回的对象键,这是您的基本模型。

       public class ErrorModel
        {
          public ErrorModel()
           {
             ErrorMessages = new List<string>();
           }
         public List<string> ErrorMessages { get; set; }
         public Exception Exception { get; set; }
       }
      
      public class BaseModel
       {
         public BaseModel()
          {
             Error = new ErrorModel();
          }
         public ErrorModel Error { get; set; }
      }
      
      
      public class BaseModel<T>: BaseModel
       {
        public BaseModel()
         {
            Error = new ErrorModel();
         }
      
       public bool HasError => Error.ErrorMessages.Count > 0 || Error.Exception != null;
      
        public T Result { get; set; }
      }
      
    • 那么你的 api 应该是这样的

       public ActionResult<BaseModel<dynamic>> Post([FromBody] NewResourceDto myNewResource)
           {
      
            try
             {
                ExampleResult result = _service.TrySaveMyNewResource(myNewResource);
                return OK( new BaseModel<dynamic>()
                {
                    Result=result
                });
             }
           catch (Exception ex)
           {
              return StatusCode(StatusCodes.Status500InternalServerError, new BaseModel<dynamic>()
               {
                  Error = new ErrorModel()
                  {
                      ErrorMessages = new List<string>()
                      {
                          ex.Message,
                          "your message 2",
                           "your message 3"
                      },
                      Exception = ex
                  }
              });
             }
         }
      
      • 然后在您的角度服务中检查您的 response.hasError 并根据它显示您的数据。

    【讨论】:

    • 感谢您的回答。这意味着每次我想访问结果时,我应该查询结果不等于 null 吗? Http状态结果呢?不应该使用 ExceptionFilters 吗?
    • @Enis,我已经编辑了我的答案,是的,你也应该使用 http 状态代码,你也可以使用 ExceptionFilters
    猜你喜欢
    • 1970-01-01
    • 2013-05-04
    • 2016-06-06
    • 2021-05-03
    • 2011-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-30
    相关资源
    最近更新 更多