首页 > 解决方案 > 在 Web API 调用导致异常后处理响应中的内容的最佳实践

问题描述

我正在开发一个 Core 3.1 Web API 和一个使用它的 MVC 应用程序。在 MVC 应用程序中,我UserRepo设置了包含向 API 发送请求的方法:

public class UserRepo : IUserRepo
{
    private readonly IHttpClientFactory _clientFactory;

    public UserRepo(IHttpClientFactory httpClientFactory)
    {
        _clientFactory = httpClientFactory;
    }

    public async Task<User> GetById(int Id)
    {
        // same code structure as Update ...
    }

    public async Task<User> Update(User user)
    {
        HttpClient client = _clientFactory.CreateClient("NamedClient");

        try
        {
            HttpResponseMessage response = await client.PutAsync($"api/Users/{user.Id}", ContentEncoder.Encode(user));
            return await response.Content.ReadFromJsonAsync<User>();
        }
        catch (Exception ex)
        {
            throw;
        }

    }

    public async Task<User> Insert(User user)
    {
        // same code structure as Update ...
    }
}

Update方法从不抛出从 API 返回的 400、404 等错误,从而导致静默错误。我发现要引起我需要调用的异常response.EnsureSuccessStatusCode();,它起作用了。

但是,异常不包含我需要找出 API 调用出了什么问题的内容。如果发生 400 错误,将抛出异常,说明发生了 400 错误,但不说明发生的原因。为什么返回给变量,response由于我已经实现了验证,它可能看起来像这样:

{
  "errors": {
    "FirstName": [
      "The FirstName field is required."
    ]
  },
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "|502d647b-4c7425oa321c8c7b."
}

是否有一种广泛使用的方法来处理 API 中产生错误后返回的响应?我想知道为什么会发生 400 错误,所以我知道要修复什么。我只是不知道处理这些响应消息的“正确”方式是什么。

我的一个想法是在每次抛出异常之前捕获异常并将其与响应文本一起记录。然后,当我的应用程序崩溃时,我可以转到日志并阅读返回的消息。该Update方法如下所示:

public async Task<User> Update(User user)
{
    HttpClient client = _clientFactory.CreateClient("NamedClient");

    HttpResponseMessage response = await client.PutAsync($"api/Users/{user.Id}", ContentEncoder.Encode(user));

    try
    {
        response.EnsureSuccessStatusCode();
    }
    catch (Exception ex)
    {
        string errorMessage =  await response.Content.ReadAsStringAsync()
        _logger.LogError(ex, errorMessage);
        throw;
    }

    return await response.Content.ReadFromJsonAsync<User>();
}

另一个想法是也许可以将消息添加到异常本身并在抛出时看到它?将消息添加为内部异常是否有意义?

标签: c#asp.net-mvcasp.net-coreasp.net-web-apidotnet-httpclient

解决方案


是否有一种广泛使用的方法来处理 API 中产生错误后返回的响应?我想知道为什么会发生 400 错误,所以我知道要修复什么。我只是不知道处理这些响应消息的“正确”方式是什么。

通常,仅记录异常详细信息,不返回。这是因为详细信息可能包括可能揭示潜在安全漏洞的个人身份信息或技术细节。有一个错误详细信息 RFC变得越来越普遍,但即使这样也不应该包含 PII 或堆栈跟踪等详细信息。

在一个 API(MVC 端点)调用另一个 API(实际 API)的情况下,MVC 端点应该返回 5xx 范围内的代码。这里可以接受 500 或 502。所有此类错误应连同其详细信息一起记录在服务器端。

请注意,如果传播异常,默认行为是返回 500,因此throw;您真正需要做的就是保留 500。但是,在“管道”中进行错误记录是很正常的,例如,ASP.NET Core 的中间件或类似 ASP.NET MVC 的全局安装的操作过滤器。这是为了确保记录所有错误,同时避免重复。


推荐阅读