.NET
O que aprendi sobre construir REST APIs em .NET
Uma API CRUD simples, sem pagamentos, nada chique. HTTP verbs, routing, EF Core, e status codes finalmente fazendo sentido enquanto eu construo.
Acabei de terminar minha primeira REST API de verdade em .NET: um app CRUD simples, sem pagamentos, nada chique. É básico, mas construir isso é onde boa parte dos fundamentos finalmente está fazendo sentido para mim.
Combinando HTTP verbs com o que eles deveriam fazer
Eu sabia que GET, POST, PUT, e DELETE existiam antes de começar isso, mas eu não entendia de fato por que importava qual você usava até construir algo com os quatro. GET lê, POST cria, PUT atualiza, DELETE remove, e cada um mapeia de forma limpa para uma action de Controller. Vendo eles lado a lado, isso para de ser uma regra abstrata e passa a ser óbvio.
Routing e Controllers
Estou usando Controllers porque é isso que todo tutorial que segui usa. [ApiController], [Route("api/products")], e uma action por HTTP verb:
[ApiController]
[Route("api/products")]
public class ProductsController : ControllerBase
{
private readonly AppDbContext _context;
public ProductsController(AppDbContext context)
{
_context = context;
}
[HttpGet]
public async Task<IActionResult> GetAll()
{
var products = await _context.Products.ToListAsync();
return Ok(products);
}
}
Pareceu muito attribute para decorar no início, mas assim que entendi que a rota e o verb juntos decidem qual action roda, isso para de parecer arbitrário.
Conversando com o database usando EF Core
Essa é a primeira vez que uso o Entity Framework Core para algo de verdade em vez do exemplo de brinquedo de um tutorial. Um model, um DbContext, e uma connection string:
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public decimal Price { get; set; }
}
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
public DbSet<Product> Products => Set<Product>();
}
Depois rodando a migration para de fato criar a tabela:
dotnet ef migrations add InitialCreate
dotnet ef database update
Essa foi a primeira vez que a API pareceu estar fazendo alguma coisa em vez de só devolver dado falso.
Status codes de fato significam algo
Antes disso eu teria devolvido 200 para basicamente tudo. Construir essa API é a primeira vez que estou prestando atenção em qual eu de fato estou mandando de volta:
[HttpGet("{id}")]
public async Task<IActionResult> GetById(int id)
{
var product = await _context.Products.FindAsync(id);
if (product is null)
{
return NotFound();
}
return Ok(product);
}
[HttpPost]
public async Task<IActionResult> Create(Product product)
{
_context.Products.Add(product);
await _context.SaveChangesAsync();
return CreatedAtAction(nameof(GetById), new { id = product.Id }, product);
}
NotFound() dá um 404, Ok() um 200, e CreatedAtAction devolve um 201 junto com a URL da coisa que acabou de ser criada. Acertar isso faz a API fazer sentido para qualquer um que a chame sem precisar ler o código.
Onde isso me deixa
Nada nesse projeto é avançado. É uma API CRUD simples com um database por trás, e a maior parte do que aprendi é só os fundamentos se encaixando pela primeira vez. É só isso por enquanto, e é suficiente para onde estou.