ASP .NET Core -  Criando uma Web API - I


  Neste artigo vamos iniciar a criação de uma WEB API usando a ASP .NET Core 3.0 para a seguir mostrar como consumir a API em uma aplicação ASP .NET Core MVC.

As WEB APIs ASP .NET Core são controladores que herdam da classe ControllerBase e que produzem como respostas objetos de dados que são enviados ao cliente sem a marcação HTML.

Vamos iniciar criando um projeto ASP .NET Core WEB APi usando o .NET Core 3.0 simples que expõe serviços para reserva de veículos.

Para não tornar o exemplo muito complexo não vou usar um banco de dados gerando os dados em memória.

Recursos :

Criando o projeto no VS 2019 Community

Abra o VS 2019 Community e crie uma solução em branco via menu File-> New Project;

Selecione o template ASP .NET Core Web Application, e, Informe o nome ApiReservas;

A seguir selecione .NET Core e ASP .NET Core 3.0 e marque o template API e as configurações conforme figura abaixo:

Clicando em Create teremos o projeto ASP .NET Core Web API criado e vamos aproveitar essa estrutura e arquivos criados para criar a nossa API de reservas.

Abaixo temos a estrutura do projeto criado:

Vamos remover os arquivos marcados pois não vamos usá-los no projeto.

Definindo o modelo de domínio e o Repositório

Vamos criar uma pasta Models no projeto e a seguir criar nesta patsa a classe Reserva que representa o nosso modelo de domínio:

    public class Reserva
    {
        public int ReservaId { get; set; }
        public string Nome { get; set; }
        public string InicioLocacao { get; set; }
        public string FimLocacao { get; set; }
    }

Na mesma pasta Models vamos criar uma interface IRepository e sua implementação e implementar o padrão Repositório para desacoplar a camada de acesso a dados e centralizar a lógica de acesso a dados.

    public interface IRepository
    {
        IEnumerable<Reserva> Reservas { get; }
        Reserva this[int id] { get; }
        Reserva AddReserva(Reserva reserva);
        Reserva UpdateReserva(Reserva reserva);
        void DeleteReserva(int id);
    }

A seguir vamos criar a classe Repository que implementa esta interface:

using System.Collections.Generic;

namespace ApiReservas.Models
{
    public class Repository : IRepository
    {
        private Dictionary<int, Reserva> items;

        public Repository()
        {
            items = new Dictionary<int, Reserva>();

            new List<Reserva> {
             new Reserva {ReservaId=1, Nome = "Macoratti", InicioLocacao = "São Paulo", FimLocacao="Lins" },
             new Reserva {ReservaId=2, Nome = "Paulo", InicioLocacao = "Campinas", FimLocacao="São Paulo" },
             new Reserva {ReservaId=3, Nome = "Maria", InicioLocacao = "Jundiaí", FimLocacao="Campinas" }
             }.ForEach(r => AddReserva(r));
        }

        public Reserva this[int id] => items.ContainsKey(id) ? items[id] : null;

        public IEnumerable<Reserva> Reservas => items.Values;

        public Reserva AddReserva(Reserva reserva)
        {
            if (reserva.ReservaId == 0)
            {
                int key = items.Count;
                while (items.ContainsKey(key)) { key++; };
                reserva.ReservaId = key;
            }
            items[reserva.ReservaId] = reserva;
            return reserva;
        }

        public void DeleteReserva(int id)
        {
            items.Remove(id);
        }

        public Reserva UpdateReserva(Reserva reserva)
        {
            AddReserva(reserva);
            return reserva;
        }
    }
}

Neste código implementamos os métodos da interface usando um Dictionary. Assim não dependendemos de um banco de dados relacional. Poderíamos também usar o Entity Framework In-Memory conforme eu mostro neste artigo: EF Core - Usando um Banco de dados In-Memory ... - Macoratti

A classe Repository cria 3 conjuntos de objetos de reserva quando é instanciada e, como não há armazenamento persistente, quaisquer alterações serão perdidas quando o aplicativo for parado ou reiniciado.

A classe contém métodos para executar operações CRUD e todas as reservas são armazenadas em um objeto do tipo Dicionário.

Configurando o arquivo Startup

A seguir vamos definir a configuração no arquivo Startup para mapear o serviço para repositório usando AddSingleton.

Na ASP .NET Core 3.0 houve para definir a configuração da Web API basta incluir o serviço AddControllers().

using ApiReservas.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace ApiReservas
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton<IRepository, Repository>();
            services.AddControllers();

        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();
            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });

        }
    }
}

Para definir o roteamento usamos app.UseRouting() e para definir os endpoints da API usamos app.UseEndPoints().

Criando o controlador ReservasController

Agora vem a parte mais importante da criação de um controlador de API. Lembre-se de que a API Controller é apenas um controlador normal que permite que os dados no modelo sejam recuperados ou modificados e entregue a algum cliente, sem precisar usar as ações fornecidas pelos controladores regulares.

A entrega dos dados é feita seguindo o padrão REST que significa Representational State Transfer, e contém 2 pontos principais:

1. Métodos Actions para executar operações específicas e, em seguida, entregar alguns dados ao cliente. Esses métodos são decorados com atributos que permitem que sejam invocados por requisições HTTP.

2. A URL à qual uma operação será aplicada. As operações podem ser - envio total ou parcial de dados, adição, exclusão ou atualização de registros.

Vamos então criar na pasta Controllers o controlador ReservasController clicando com o botão direito do mouse sobre a pasta Controllers e a seguir em Add -> Controller;

A seguir selecione o template - API Controller - Empty e clique em Add;

Informe o nome ReservasController e clique em Add.

Serão instalados os pacotes necessários e o controlador será criado.

A seguir inclua o código abaixo no arquivo ReservasController.cs :

using ApiReservas.Models;
using Microsoft.AspNetCore.JsonPatch;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;

namespace ApiReservas.Controllers
{
    [Route("api/[controller]")]
    [ApiController]

    public class ReservasController : ControllerBase
    {
        private IRepository repository;

        public ReservasController(IRepository repo) => repository = repo;

        [HttpGet]
        public IEnumerable<Reserva> Get() => repository.Reservas;

        [HttpGet("{id}")]
        public Reserva Get(int id) => repository[id];

        [HttpPost]
        public Reserva Post([FromBody] Reserva res) =>
        repository.AddReserva(new Reserva
        {
            Nome = res.Nome,
            InicioLocacao = res.InicioLocacao,
            FimLocacao = res.FimLocacao

        });

        [HttpPut]
        public Reserva Put([FromForm] Reserva res) => repository.UpdateReserva(res);

        [HttpPatch("{id}")]
        public StatusCodeResult Patch(int id, [FromForm]JsonPatchDocument<Reserva> patch)
        {
            Reserva res = Get(id);
            if (res != null)
            {
                patch.ApplyTo(res);
                return Ok();
            }
            return NotFound();
        }

        [HttpDelete("{id}")]
        public void Delete(int id) => repository.DeleteReserva(id);
    }
}

Temos que incluir no projeto uma referência ao pacote: Microsoft.AspNetCore.JsonPatch.

Agora, antes de prosseguir, vamos alterar a configuração do projeto acessando as suas propriedades e na guia Debug definindo os valores abaixo:

Pronto ! vamos agora analisar o código do controlador.

Faremos isso na próxima parte do artigo.

Pegue o código do projeto (sem as referências) : ApiReservas.zip

"Tendo sido, pois, justificados pela fé, temos paz com Deus, por nosso Senhor Jesus Cristo;
Pelo qual também temos entrada pela fé a esta graça, na qual estamos firmes, e nos gloriamos na esperança da glória de Deus."

Romanos 5:1,2

Referências:


José Carlos Macoratti