如何在 ASP.NET MVC Web 应用程序中使用 HttpContent 处理并发状态 409错误?

问题描述

我正在研究 Core 3.1 Web API 和使用它的 MVC 应用程序。在 MVC 应用程序中,我设置了包含 Update 方法的 UserRepo:

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)
    {
        if ((int)response.StatusCode == StatusCodes.Status409Conflict)
        {
            throw;
        }
    }

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

repo 被注入到一个服务中,而该服务被注入到一个控制器中,这是我想要处理错误的地方。

Update 方法不完整,因为我试图弄清楚如果 rowversion 值已过时,我如何处理从 API 返回的 409 错误调用 response.EnsureSuccessstatusCode(); 时,如果不是成功代码,则会引发异常。我想我可以让它冒泡到前端并在控制器操作中处理它,但异常对象不包含任何足够具体的内容来识别它是 409 错误

enter image description here

因此,如果这冒泡到控制器操作,我所能做的就是尝试从 message 中解析出状态代码,这似乎是个坏主意。

我可以找到人们从他们的 Web API 返回 409 代码的例子,但没有找到当逻辑被分成不同的类而不是全部在一个动作中时在 MVC 应用程序中如何处理这些代码的例子。

我该如何处理?我是否创建自定义异常并抛出该异常?也许使用 ex.Data.Add() 向异常添加其他数据并在操作中读取它?这是个坏主意吗?

解决方法

感谢@Peter Csala、@Craig H 和 @Filipe 的建议,这是我确定的解决方案。

调用API的方法:

public async Task<User> Update(User user)
{
    HttpClient client = _clientFactory.CreateClient("namedClient");
    HttpResponseMessage response = await client.PutAsync($"api/Users/{user.Id}",ContentEncoder.Encode(user));
    await HttpResponseValidator.ValidateStatusCode(response);

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

我可以重用的静态方法,它会在并发错误期间产生异常:

public static class HttpResponseValidator
{
    public static async Task ValidateStatusCode(HttpResponseMessage response)
    {
        if ((int)response.StatusCode < 200 || (int)response.StatusCode > 299)
        {
            string errorResponse = await response.Content.ReadAsStringAsync();
            if (response.StatusCode == HttpStatusCode.Conflict)
            {
                DBConcurrencyException ex = new DBConcurrencyException(errorResponse);
                throw ex;
            }
        }
    }
}

异常一直冒泡到调用 API 的方法的操作。我在 action 中捕获它并在记录错误后处理它。