DevSecOps

18 out, 2018

ASP.NET Core 2.1: simplificando a codificação com o atributo ApiController

Publicidade

O atributo ApiController é mais uma das novidades do ASP.NET Core 2.1 voltadas à implementação de APIs REST. Associado a um Controller, este atributo contribui para a obtenção de projetos com um código mais enxuto e limpo.

Para exemplificar o uso do atributo ApiController, será tomada como base a classe detalhada na listagem a seguir. No tipo Comentario é possível observar o uso de Data Annotations com os campos Nome e Mensagem:

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace APIComentarios.Models
{
    public class Comentario
    {
        public Guid? Id { get; set; }
        public DateTime? Data { get; set; }

        [Required]
        [MaxLength(60)]
        public string Nome { get; set; }

        [Required]
        public string Mensagem { get; set; }
    }
}

Já na próxima listagem é possível observar a definição da classe ComentariosController:

  • O parâmetro comentario da Action Post foi marcado no atributo FromBody, indicando que as informações esperadas para o mesmo estarão no corpo de uma requisição HTTP recebida por esse método;
  • Uma validação no início da Action Post verificará se os dados associados ao parâmetro comentario são válidos, com isso acontecendo por meio da propriedade IsValid do objeto ModelState. Um erro do tipo 400 (Bad Request) será então retornado caso alguma das restrições definidas via Data Annotations seja violada.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using APIComentarios.Data;
using APIComentarios.Models;

namespace APIComentarios.Controllers
{
    [Route("api/[controller]")]
    public class ComentariosController : ControllerBase
    {
        [HttpGet]
        public IEnumerable<Comentario> Get(
            [FromServices]ApplicationDbContext context)
        {
            return context.Comentarios.ToArray();
        }

        [HttpPost]
        public IActionResult Post(
            [FromBody]Comentario comentario,
            [FromServices]ApplicationDbContext context)
        {
            if (!ModelState.IsValid)
                return BadRequest(ModelState);

            comentario.Id = Guid.NewGuid();
            comentario.Data = DateTime.Now;
            context.Comentarios.Add(comentario);
            context.SaveChanges();

            return Ok();
        }
    }
}

Introduzido a partir da versão 2.1 do ASP.NET Core, o atributo ApiController veio para simplificar a codificação de Controllers como o detalhado neste artigo. A seguir temos uma versão refatorada da classe ComentariosController, em que é possível destacar:

  • O parâmetro comentario não foi marcado com FromBody, já que a presença do atributo ApiController torna possível inferir que o conteúdo associado a este elemento se encontra no corpo de uma requisição;
  • A instrução que checa o conteúdo da propriedade IsValid no objeto ModelState também foi removida. Qualquer inconsistência decorrente de violação das regras nas Data Annotations da classe Comentario resultará na geração automática de um erro do tipo 400 (Bad Request).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using APIComentarios.Data;
using APIComentarios.Models;

namespace APIComentarios.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ComentariosController : ControllerBase
    {
        [HttpGet]
        public IEnumerable<Comentario> Get(
            [FromServices]ApplicationDbContext context)
        {
            return context.Comentarios.ToArray();
        }

        [HttpPost]
        public IActionResult Post(
            Comentario comentario,
            [FromServices]ApplicationDbContext context)
        {
            comentario.Id = Guid.NewGuid();
            comentario.Data = DateTime.Now;
            context.Comentarios.Add(comentario);
            context.SaveChanges();

            return Ok();
        }
    }
}

O envio via Postman de uma requisição com dados inválidos trará como retorno um erro do tipo 400, conforme indicado na imagem a seguir:

Referências