【问题标题】:How to handle concurrency (status 409) errors using HttpContent in ASP.NET MVC Web application?如何在 ASP.NET MVC Web 应用程序中使用 HttpContent 处理并发(状态 409)错误?
【发布时间】:2021-01-19 14:51:43
【问题描述】:

我正在开发一个 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 错误:

因此,如果这冒泡到控制器操作,我最好的办法是尝试从 message 解析出状态代码,这似乎是个坏主意。

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

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

【问题讨论】:

  • 将其捕获为HttpRequestException 而不是一般的Exception。见docs.microsoft.com/en-us/dotnet/api/…
  • @Leandro 感谢您的建议。我已经尝试过了,但异常对象看起来与Exception 的对象相同。我没有看到单独的 StatusCode 属性。
  • 我现在看到 StatusCode 属性是在 Core 5.0 中引入的。我在 3.1 上。
  • 我明白了。另一种选择是创建您自己的自定义异常。
  • 如果没有其他人提出更多建议,我可能最终会做类似的事情,因为我找不到处理它的好方法。感谢您的帮助。

标签: c# asp.net-mvc asp.net-core asp.net-web-api dotnet-httpclient


【解决方案1】:

感谢@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 的方法的操作。我在操作中捕获它并在记录错误后处理它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-10
    • 1970-01-01
    • 1970-01-01
    • 2023-01-12
    • 1970-01-01
    相关资源
    最近更新 更多