【问题标题】:Returning meaningful error messages from a .NET Core API从 .NET Core API 返回有意义的错误消息
【发布时间】:2019-08-11 05:31:05
【问题描述】:

场景

我有一个带有异常处理中间件的 .NET Core 2.2 Web API。每当应用程序(在 MVC 层内)发生异常时,它就会被异常中间件捕获并作为内部服务器错误返回到前端并记录到 kibana。

问题

当出现问题时,这一切都很好,但有时我想具体通知调用应用程序出了什么问题。即,“在数据库中找不到记录!”或“无法将这个转换成那个!”

我的解决方案

我已经使用应用程序异常(不是很好 - 我知道)来捎带错误中间件以将其返回到前端。这一直工作得很好,但是由于不得不抛出一大堆异常而在代码周围产生了很多噪音。我对这种方法并不满意,并坚信一定有更好的解决方案。

我的应用程序架构:我遵循传统的 n-tier application 布局,即服务(业务逻辑)和存储库 (DAL) 都相互通信。我希望在任何这些层中优雅地将任何问题反馈给用户。

我一直在考虑这个问题,但不确定最好的方法是什么。任何建议将不胜感激。

【问题讨论】:

  • 能否在调用应用程序中添加一个事件监听器来监听中间件的异常处理事件?
  • @L0uis 这是可能的,但不确定这将如何让我实现我想要的。

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


【解决方案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

【讨论】:

  • 我喜欢这个,唯一的问题是必须将所有内容都包含在 OperationResult 泛型中。我将在所有具体实现中的代码库中都有这个。
  • 我决定用这个!
【解决方案2】:

根据 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;
}

【讨论】:

    猜你喜欢
    • 2020-09-07
    • 2020-08-05
    • 2019-12-26
    • 2021-11-27
    • 2020-05-29
    • 1970-01-01
    • 2020-01-18
    • 2019-05-31
    • 2020-12-01
    相关资源
    最近更新 更多