How to handle concurrency (status 409) errors using HttpContent in ASP.NET MVC Web application?

耗尽温柔 提交于 2021-01-29 15:31:07

问题


I'm working on a Core 3.1 Web API and an MVC application that uses it. In the MVC app I have UserRepo set up containing an Update method:

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>();
}

The repo is injected into a service, and the service is injected into a controller which is where I'd like to handle the error.

The Update method is incomplete because I am trying to figure out how handle a 409 error which I return from API if the rowversion value was outdated. When response.EnsureSuccessStatusCode(); is called, an exception is thrown if it wasn't a success code. I imagined I could just have it bubble-up to the front-end and handle it in the controller action, but the exception object doesn't contain anything specific enough to identify that it's a 409 error:

So if this bubbles up to the controller action, best I could to is try to parse out the status code from the message, which seems like a bad idea.

I can find examples of people returning 409 codes from their Web APIs, but not how they would be handled in an MVC app when logic is separated into different classes instead of being all in one action.

How could I handle this? Do I create a custom exception and throw that? Maybe add additional data to the exception with ex.Data.Add() and read it in the action? Would that be a bad idea?


回答1:


Thanks to suggestions from @Peter Csala, @Craig H, and @Filipe, this is the solution I settled on.

Method that calls the 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>();
}

A static method I can reuse that will produce an exception during a concurrency error:

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

The exception bubbles up all the way back to the action that called the method calling the API. I catch it in the action and handle it after logging the error.



来源:https://stackoverflow.com/questions/65793934/how-to-handle-concurrency-status-409-errors-using-httpcontent-in-asp-net-mvc-w

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!