How to format response data for your Web API in ASP.NET Core
When we develop API, we develop a user interface. Like any modern user interface, it should have a certain level of usability. Front-end developers, in most cases, your API users, should be able to work with and get proper responses. There is no industry standard or perfect response, each of us is having own vision of what to return and when.
I'm facing projects which were developed for decades, and in most cases, several different people or teams worked on it during this time. Different people - different coding styles, approaches, and understanding. In my opinion, It doesn't matter how you going to design your API responses, more important is to be consistent in your project. Consistency might help you not only avoid a coding mess but also speed up front-end development and new developers' onboarding process.
In this post, I going to share my opinion about the topic.
I would like to highlight a few usability topics each API should have:
- It should be fast - it should be fast enough.
- State - A developer should be aware of what happens and why.
- Documentation - Industry-standard especially when API is shipped.
Speed
No one these days will wait for your API response. The threshold of 500-1000ms will be a good starting point. There is a variety of ways to measure execution time for your API, including saas and pass solutions.
State
It should be represented by a proper HTTP code. There are several common that can cover 95% of responses:
401
Authorization error. Addresses any problem related to tokens and token expiration. In .net world implemented with controller's/action's Authorize
attribute.
400
Validation errors. Requests should must be validated and Bad Request
is the correct response to notify the developer that his request is wrong.
404
Not found.
500
Server error. Addresses errors happen during the execution. You choose what details to show the world: It can be an error message as it comes from the data access layer or something generic that doesn't expose the details (more secure way).
20x
200 for ok or 201 for created as successful completion of the request.
Documentation
OpenAPI format is a great way to generate documentation for your API and swagger
is the easy way to implement it, especially with XML comments. Don't forget to switch swagger off when going to production.
The problem with documentation is that there is always not enough documentation. Try to get feedback from your API clients, usually a front-end team and add the missing parts.
The response data
In my previous GetInfra WebApi Abstractions introduction, I introduced the library I use for POST
, PUT
and DELETE
methods.
Let's take as an example simple post request handling:
[HttpPost]
public async Task<ActionResult<GenericResponse<string>>> Post(SomeRequest request)
{
// validate
var r = await _someValidator.ValidateAsync(request);
// convert to generic response
var result = r.ToGenericResponse<string>();
if (!result.IsValid)
// return 400
return BadRequest(result);
try
{
// service call
result = await _someService.CreateAsync(request);
// return 201
return Created(new Uri($"https://some.domain-com/path/{result.Id}"), result);
}
catch (Exception ex)
{
_logger.LogError(ex, "POST error: {0}, stack:", ex.Message, ex.StackTrace);
result.Errors.Add(new ErrorItem(ex.Message, ex.StackTrace));
// return 500
return StatusCode(500, result);
}
}
As a first step, it validates if the request is ok and we can work with it. I use IValidator<T>
from GetInfra.WebApi.Abstractions for interface and abstractions with my custom SomeRequestValidator
implementation to validate the request. I will provide a detailed review of request validation in my next posts. In case of a validation error, it will return status 400
along with validation error(s).
The second step is the actual call for business logic data access chain, which in case the error will be handled with try..catch
statement, will log and return 500
status.
Finally, if everything goes smooth it will return status 201 with newly generated id (as an example below):
{
"succeeded": true,
"id": "11111111",
"errors": [],
"valiationErrors": [],
"isValid": true
}
If you like my approach, you can install the NuGet package:
Install-Package GetInfra.WebApi.Abstractions
If you don't please tell me why.
The example project can be found on github
Happy coding and stay safe!
🚀 Turbocharge Your Infrastructure with Our Terraform Template Kits! 🚀
🌟 Slash deployment time and costs! Discover the ultimate solution for efficient, cost-effective cloud infrastructure. Perfect for DevOps enthusiasts looking for a reliable, scalable setup. Click here to revolutionize your workflow!
Learn More about Starter Terraform Kits for AKS,EKS and GKE
No comments are allowed for this post