본문 바로가기

Marketing and SEO

Creating a Unified Error Response Format

반응형

Error messages returned from each error have differenct formats and this makes it hard for front developers to work with. We will see how we can solve this problem.

 

Let's see first what I meant about the different format of each errors

404
500
400
400

Implementation

1) For .NET MVC Controller Based Errors

Error code methods that MVC controller provides can take a format as a parameter

 

Create a folder to handle errors in the API folder

Add a class to provide a unified format

Add a constructor, properties, and a method as shown below

// constructor
public ErrorRes(int statusCode, string massage = null)
{
  this.StatusCode = statusCode;      
  this.Message = massage ?? GetStatusCodeMessage(statusCode);
}

// properties
public int StatusCode { get; set; }
public string Message { get; set; }

// method
private string GetStatusCodeMessage(int statusCode)
{
  return statusCode switch
  {
    400 => "bad request",
    401 => "Unauthorized",
    404 => "Resource not found",
    500 => "Server error",
    _ => null,
  };
}

Use the class as a parameter to the MVC error method

2) For endpoints that does not exist

Add a controller to handle the reqeust to the not existing endpoint

Update the class as shown below

[ApiController]
[Route("errors/{code}")]
[ApiExplorerSettings(IgnoreApi = true)]
public class NotFoundController : ControllerBase
{
  public IActionResult Error(int code)
  {
    return new ObjectResult(new ErrorRes(code));
  }
}

Go to the Program.cs file and add the code below to redirect calls to unknown endpoints to the controller we just created

app.UseStatusCodePagesWithReExecute("/errors/{0}");

3) Adding Error Messages

Add a class that adds error messages

Inherit from the base error class and add additional properties (e.g., 'Details')

public class ErrorSource : ErrorRes
{
  public ErrorSource(
    int statusCode,
    string massage = null,
    string details = null
    ) : base(statusCode, massage)
  {
    this.Details = details;
  }

  public string Details { get; set; }
}

Create a folder for middleware

Add a class that handles the error

Insert this code

private readonly RequestDelegate _next;
private readonly ILogger<ExceptionMiddleware> _logger;
private readonly IHostEnvironment _env;
public ExceptionMiddleware(
  RequestDelegate next,
  ILogger<ExceptionMiddleware> logger,
  IHostEnvironment env)
{
  this._next = next;
  this._logger = logger;
  this._env = env;
}

public async Task InvokeAsync(HttpContext context)
{
  try
  {
    await _next(context);
  }
    catch (Exception ex)
  {
    _logger.LogError(ex, ex.Message);
    context.Response.ContentType = "application/json";
    context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
    var res = _env.IsDevelopment() ? new ErrorSource(
      (int)HttpStatusCode.InternalServerError,
      ex.Message,
      ex.StackTrace.ToString()
      ) : new ErrorSource((int)HttpStatusCode.InternalServerError);
    var options = new JsonSerializerOptions
    {
      PropertyNamingPolicy = JsonNamingPolicy.CamelCase
    };
    var json = JsonSerializer.Serialize(res, options);
    await context.Response.WriteAsync(json);
  }
}

Go to the Program.cs file and register the middleware

4) Changing an Object to an Array of Strings

Error messages are provided by [ApiController] meta tag. So to change the format of provided error messages, we have to add an option to the meta tag

Create a class to handle this task

public class ErrorValidation : ErrorRes
{
  public ErrorValidation() : base(400)
  {        
  }

  public IEnumerable<string> Errors { get; set; }
}

Go to the Program.cs file and register a service that changes [ApiController] settings

builder.Services.Configure<ApiBehaviorOptions>(opt =>
{
  opt.InvalidModelStateResponseFactory = actionContext =>
  {
    var errors = actionContext.ModelState
    .Where(e => e.Value.Errors.Count > 0)
    .SelectMany(x => x.Value.Errors)
    .Select(x => x.ErrorMessage).ToArray();

    var errorRes = new ErrorValidation
    {
      Errors = errors
    };

    return new BadRequestObjectResult(errorRes);
  };
});

We have seen how we can provide a better experience to frontend developers by sending them error message reponses with a unified format

 

728x90
반응형

'Marketing and SEO' 카테고리의 다른 글

Google Search  (0) 2023.04.21
SEO (Multi-Lingual Blog Indexing)  (9) 2023.04.21
Robots.txt  (0) 2023.04.14