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: