Home > Software design >  How to handle API responses globally in ASP.NET MVC controller?
How to handle API responses globally in ASP.NET MVC controller?

Time:10-01

I have a couple of controller methods that call APIs and I handle the responses using a switch statement like the one below.

Question:

  1. Is there a way to refactor my code to handle the responses from one place instead of having pretty much the same switch statement in every request? NOTE: I have a BearerTokenHandler class file. Could I handle the responses there?
var apiResponse = _httpClient.PostAsync()

switch (apiResponse.StatusCode)
{
  case HttpStatusCode.OK:
    //Parse response
  break:

  case HttpStatusCode.BadRequest:
    //Parse response
  break:

  case HttpStatusCode.NotFound:
    //Parse response
  break

  case HttpStatusCode.Unauthorized:
    return RedirectToAction("AccessDenied");

  default:
    // ViewData["Error"]
  break:
}

CodePudding user response:

You could have a BaseContoller class that accepts a generic model to post and then each of your post methods can just call this instead.

CodePudding user response:

There are a lot of ways you can refactor your code. Here I just point out the two most common ways.

  1. Make an HttpClient service and put all the work (POST, GET) relate to HttpClient there
  2. Have a BaseController and generic methods. Then inherit all common works there.

It's better to combine two ways, which means always having a BaseController and made some services to handle related things.

Here is the example code:

public class BaseController : Controller
{
    // Put all the cross cutting-concern things here
    // Like: Object Mapper, Logger, Cache Manager, etc...
    // So that you can use them without re-initialize
}

Make the interface IHttpClientService and its implementation HttpClientService. If you're using the ASP.NET Core then use its default Dependency Injection, otherwise if you using the old ASP.NET MVC, read this Dependency Injection


public interface IHttpClientService
{
    Task<IActionResult> PostAsync();
}

public class HttpClientService : IHttpClientService
{
    public async Task<object> PostAsync()
    {
        var _httpClient = new HttpClient();
        var apiResponse = _httpClient.PostAsync();

        switch (apiResponse.StatusCode)
        {
            case HttpStatusCode.OK:
                //Parse response
                break;

            case HttpStatusCode.BadRequest:
                //Parse response
                break;

            case HttpStatusCode.NotFound:
                //Parse response
                break;

            case HttpStatusCode.Unauthorized:
                return RedirectToAction("AccessDenied");

            default:
                // ViewData["Error"]
                break;
        }
    }
}

Then you can implement your controller

public class YourController : BaseController
{
    private readonly IHttpClientService _httpClientService;

    public YourController(IHttpClientService httpClientService)
    {
        _httpClientService = httpClientService;
    }

    public async Task<IActionResult> YourMethod()
    {
        var result = await _httpClientService.PostAsync();
        // You can use the logger from the BaseController to do something here
        return result;
    }
}
  • Related