从Net Core API返回有意义的错误消息

时间:2019-03-20 13:43:09

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

场景: 我有一个带有异常处理中间件的.net核心2.2 Web API。只要应用程序中发生异常(在MVC层内部),异常中间件就会捕获该异常,并将其作为内部服务器错误返回给前端并记录到kibana。

问题:当出现问题时,这一切都很好,但有时我想通知发生问题的调用应用程序。即“在数据库中找不到记录!”或“无法将其转换为该字符!”

我的解决方案:我使用应用程序异常(不是很好-我知道)来带走错误中间件,以将其返回到前端。这样做一直很好,但是由于必须抛出大量异常,因此在代码周围产生了很多噪音。我对此方法不满意,并坚信必须有更好的解决方案。

我的应用程序体系结构:我遵循传统的n层应用程序布局,即服务(业务逻辑)和存储库(DAL)都在互相交谈。我最好希望在所有这些层中优雅地将所有问题反馈给用户。

我已经考虑了一段时间,但不确定最好的解决方法是什么。任何建议将不胜感激。

2 个答案:

答案 0 :(得分:1)

我使用一种操作结果模式(非官方模式)。

原理是返回包含以下内容的新Type:

  • 手术是否成功。
  • 操作结果是否成功。
  • 有关导致失败的异常的详细信息。

请考虑以下课程:

public class OperationResult
{
    protected OperationResult()
    {
        this.Success = true;
    }
    protected OperationResult(string message)
    {
        this.Success = false;
        this.FailureMessage = message;
    }
    protected OperationResult(Exception ex)
    {
        this.Success = false;
        this.Exception = ex;
    }
    public bool Success { get; protected set; }
    public string FailureMessage { get; protected set; }
    public Exception Exception { get; protected set; }
    public static OperationResult SuccessResult()
    {
        return new OperationResult();
    }
    public static OperationResult FailureResult(string message)
    {
        return new OperationResult(message);
    }
    public static OperationResult ExceptionResult(Exception ex)
    {
        return new OperationResult(ex);
    }
    public bool IsException()
    {
        return this.Exception != null;
    }
}

然后,您可以轻松地修改OperationResult或创建一个从OperationResult继承但使用通用类型参数的类。

一些例子:

  1. The Operation Result Pattern — A Simple Guide
  2. Error Handling in SOLID C# .NET – The Operation Result Approach

答案 1 :(得分:0)

根据Microsoft的标准,在出现4xx / 5xx异常的情况下,最好使用ProblemDetails对象-

以下是自定义的RequestDelegate方法,您可以在ApiExceptionHandler中使用该方法来处理异常。希望这会有所帮助!

public async Task RequestDelegate(HttpContext context)
        {
            var exception = context.Features.Get<IExceptionHandlerFeature>().Error;
            var problemDetails = new ProblemDetails
            {
                Title = "An unexpected error occurred!",
                Status = GetStatusCode(exception),
                Detail = _env.IsDevelopment() ? exception.Message : "An unexpected error occurred!",
                Instance = $"{Environment.MachineName}:{context.TraceIdentifier}:{Guid.NewGuid()}"
            };

            _logger.LogError($"Exception thrown. StatusCode: {problemDetails.Status}. Instance: {problemDetails.Instance}", exception);

            context.Response.StatusCode = problemDetails.Status.Value;
            context.Response.WriteJson(problemDetails, "application/problem+json");

            await Task.CompletedTask;
        }