.NET

13 abr, 2018

ASP.NET Core 2.1: utilizando ActionResult<T> no retorno de APIs

Publicidade

Recentemente iniciei uma série sobre as novidades do ASP.NET Core 2.1 (que ainda se encontra em Preview). O primeiro artigo abordou o suporte a HTTPS, característica esta, que será default nesta nova versão da plataforma Web da Microsoft:

Neste novo artigo, abordo o uso do tipo genérico ActionResult<T>, estrutura concebida com o objetivo de simplificar a codificação de instruções de retorno em APIs. Em um artigo anterior sobre APIs REST no ASP.NET Core 2.0, detalhei o uso de mensagens de erro customizadas em APIs REST:

A listagem a seguir retoma o exemplo envolvendo a classe CatalogoController:

  • Analisando a estrutura destes métodos é possível notar que o retorno dos mesmos é uma instância baseada na interface IActionResult (namespace Microsoft.AspNetCore.Mvc);
  • Ao informar um código válido e um item for encontrado, o retorno destas construções será uma instância do tipo ObjectResult (namespace Microsoft.AspNetCore.Mvc) contendo um produto ou serviço;
  • Se tratando de um código inválido ou que corresponda a um item não existente, será então acionado o método NotFound (namespace Microsoft.AspNetCore.Mvc). Como resultado, teremos a geração de um erro do tipo 404 (indicativo de um recurso não encontrado).
using Microsoft.AspNetCore.Mvc;

namespace APICatalogo.Controllers
{
    [Route("api/[controller]")]
    public class CatalogoController : Controller
    {
        private CatalogoContext _contexto;

        public CatalogoController(CatalogoContext context)
        {
            _contexto = context;
        }

        [HttpGet("produtos/{codigo}")]
        public IActionResult GetProduto(string codigo)
        {
            Produto prod = null;
            if (codigo.StartsWith("PROD"))
                prod = _contexto.ObterItem<Produto>(codigo);

            if (prod != null)
                return new ObjectResult(prod);
            else
            {
                return NotFound(
                    "Código de produto inválido ou item inexistente.");
            }
        }

        [HttpGet("servicos/{codigo}")]
        public IActionResult GetServico(string codigo)
        {
            Servico serv = null;
            if (codigo.StartsWith("SERV"))
                serv = _contexto.ObterItem<Servico>(codigo);

            if (serv != null)
                return new ObjectResult(serv);
            else
            {
                return NotFound(
                    new
                    {
                        Mensagem = "Código de serviço inválido ou item inexistente.",
                        Erro = true
                    });
            }
        }
    }
}

Com ActionResult<T> podemos agora simplificar tal implementação, dispensando assim, o uso da classe ObjectResult (o retorno, neste caso, será a própria instância do tipo indicado por T em ActionResult<T>):

using Microsoft.AspNetCore.Mvc;

namespace APICatalogo.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class CatalogoController : ControllerBase
    {
        private CatalogoContext _contexto;

        public CatalogoController(CatalogoContext context)
        {
            _contexto = context;
        }

        [HttpGet("produtos/{codigo}")]
        public ActionResult<Produto> GetProduto(string codigo)
        {
            Produto prod = null;
            if (codigo.StartsWith("PROD"))
                prod = _contexto.ObterItem<Produto>(codigo);

            if (prod != null)
                return prod;
            else
            {
                return NotFound(
                    "Código de produto inválido ou item inexistente.");
            }
        }

        [HttpGet("servicos/{codigo}")]
        public ActionResult<Servico> GetServico(string codigo)
        {
            Servico serv = null;
            if (codigo.StartsWith("SERV"))
                serv = _contexto.ObterItem<Servico>(codigo);

            if (serv != null)
                return serv;
            else
            {
                return NotFound(
                    new
                    {
                        Mensagem = "Código de serviço inválido ou item inexistente.",
                        Erro = true
                    });
            }
        }
    }
}

É possível observar nas imagens a seguir os retornos produzidos pela Action GetProduto:

E pela Action GetServico:

Referências