ASP .NET Core -  Criando APIs com o framework Carter


Hoje vamos apresentar o framework Carter e mostrar como criar APIs usando alguns dos seus recursos.

O Carter é um framework que é uma camada fina de métodos de extensão e funcionalidades sobre a ASP.NET Core, permitindo que o código seja mais explícito, o roteamento mais elegante e além disso adiciona o suporte a Fluent Validation.

Para entender melhor como o Carter funciona vamos criar um projeto API de exemplo que vai fazer o CRUD básico usando o EF Core em uma tabela Clientes do SQL Server.

Fazendo um CRUD básico com Carter

Podemos instalar o template CarterTemplate  : dotnet new-i CarterTemplate

E após isso podemos criar projetos usando o template : dotnet new Carter -n <nome>

Neste primeiro contato vamos criar um projeto Web API usando o template ASP. NET Core Empty no Visual Studio 2019 e nomeá-lo Aspn_Carter.

A seguir vamos incluir o pacote Nuget Carter :

A seguir precisamos configurar o projeto para usar o Carter no arquivo Startup:

    public class Startup
    {
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddCarter();
            }

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

            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                  if (env.IsDevelopment())
                  {
                      app.UseDeveloperExceptionPage();
                  }

                   app.UseRouting();
                   app.UseEndpoints(endpoints => endpoints.MapCarter());
            });
        }
    }

No código além de incluir o serviço do Carter também definimos o mapeamento para os endpoints.

Com isso podemos iniciar o desenvolvimento da nossa aplicação.

No Carter os endpoints são definidos em módulos que são classes que herdam da classe CarterModule.

Assim vamos iniciar criando uma pasta Modules no projeto onde vamos definir os módulos usados no projeto.

A seguir vamos criar a pasta Models e nesta pasta vamos criar a classe:

    public class Cliente
    {
        public int Id { get; set; }
        public string Nome { get; set; }
        public string Email { get; set; }
    }

Na mesma pasta Models vamos criar a classe de contexto AppDbContext que herda de DbContext e define o mapeamento ORM para a entidade Cliente:

using Microsoft.EntityFrameworkCore;

namespace Aspn_Carter.Models
{
    public class AppDbContext : DbContext
    {
        public AppDbContext(DbContextOptions<AppDbContext> options): base(options)
        {}
        public DbSet<Cliente> Clientes { get; set; }
    }
}

A seguir vamos registrar o contexto como um serviço e definir o provedor do banco de dados e  a string de conexão com o SQL Server no arquivo Startup:

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<AppDbContext>(options =>
                options.
UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

            services.AddCarter();
        }

A string de conexão 'DefaultConnection'  deve ser definida no arquivo appsettings.json:

{
  "ConnectionStrings": {
    "DefaultConnection": "
Data Source=*******;Initial Catalog=Teste;Integrated Security=True"
  },

  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}   

A string de conexão do meu ambiente usa o banco de dados Teste e a tabela Clientes que já existe e já contém alguns dados conforme abaixo:

Definindo as APIs HomeModule e ClienteModule

Vamos criar na pasta Modules duas APIs que iremos usar.

A primeira será a classe HomeModule com o código abaixo:

using Carter;
using Microsoft.AspNetCore.Http;
namespace Aspn_Carter.Modules
{
    public class HomeModule : CarterModule
    {
        public HomeModule()
        {
            this.Get("/", (req, res) =>
            {
                res.StatusCode = 409;
                return res.WriteAsync("Bem-Vindo ao Carter");
            });
        }
    }
}

Este endpoint será acessado quando da inicialização da aplicação exibindo a mensagem 'Bem-Vindo ao Carter'.

A seguir vamos criar a API que vai tratar de expor os endpoints para gerenciar as informações dos Clientes.

Para isso vamos criar a classe ClientesModule com o código abaixo:

using Aspn_Carter.Models;
using Carter;
using Carter.ModelBinding;
using Carter.Request;
using Carter.Response;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;

namespace Aspn_Carter.Modules
{
    public class ClienteModule : CarterModule
    {
        public readonly AppDbContext _context;
        public ClienteModule(AppDbContext context)

        {
            _context = context;

            Get("/cliente/", (req, res) =>
            {
                var clientes = _context.Clientes;
                return res.WriteAsJsonAsync(clientes);
            });

            Get("/cliente/{id:int}", (req, res) =>
            {
                var id = req.RouteValues.As<int>("id");
                var cliente = _context.FindAsync<Cliente>(id);
                return res.Negotiate(cliente);
            });

            Post("/cliente/", async (req, res) =>
            {
                var cliente = await req.Bind<Cliente>();

                _context.Add(cliente);
                _context.SaveChanges();
                 res.StatusCode = 201;
                await res.Negotiate(cliente);
                return;
            });

            Put("/cliente/{id:int}", async (req, res) =>
            {
                var cliente = await req.Bind<Cliente>();

                cliente.ClienteId = req.RouteValues.As<int>("id");

                _context.Update(cliente);
                 _context.SaveChanges();

                 res.StatusCode = 204;
                return;
            });

            Delete("/cliente/{id:int}", (req, res) =>
            {
                 var cliente = await req.Bind<Cliente>();
                 cliente.ClienteId = req.RouteValues.As<int>("id");

                 _context.Remove(cliente);
                  _context.SaveChanges();

                   res.StatusCode = 204;
                   return;
            });
        }
    }
}

No código da API definimos cinco endpoints :

  1. GET -  Get("/cliente/", (req, res)
  2. GET -  Get("/cliente/{id:int}", (req, res)
  3. POST -  Post("/cliente/", async (req, res)
  4. PUT -   Put("/cliente/{id:int}", async (req, res)
  5. DELETE - Delete("/cliente/{id:int}", (req, res)

Em cada um deles implementamos a respectiva operação consultar, atualizar e excluir dados fazendo assim o CRUD básico em nossa tabela Clientes do SQL Server.

Testando a API com Postman

Para testar cada um dos endpoints vamos usar o Postman.

Nota: Para instalar o Postman acesse esse link : https://www.getpostman.com/apps ou abra o Google Chrome e digite postam e a seguir clique no link:  Postman - Chrome Web Store

Para executar a aplicação selecione Aspn_Carter e execute o projeto.

A seguir abrindo o Postman vamos realizar os testes para cada endpoint:

1- Get - Get("/cliente/", (req, res)  -Retorna todos os clientes;

GET  https://localhost:5001/Cliente

2- Get - Get("/cliente/{id:int}", (req, res)  -Retorna um cliente pelo id;

GET  https://localhost:5001/Cliente/12

3- Post - Post("/cliente/", async (req, res) - Inclui um novo cliente;

POST  https://localhost:5001/Cliente/

{
  "nome": "Marta Rocha",
  "email": "martarocha@teste.com"
}

4- Put - Get("/cliente/{id:int}", (req, res)  -  Atualiza os dados de um cliente;

PUT  https://localhost:5001/Cliente/12

{
  "ClienteId" : 12,
  "nome": "Marta Silveira Lima",
  "email": "martasilveiralima@teste.com"
}

5- Delete - Delete("/cliente/{id:int}", (req, res)  - Excluir um cliente pelo id;

DELETE  https://localhost:5001/Cliente/12

Como vemos todas as operações CRUD foram realizadas com sucesso.

Em outro artigo vamos mostrar como implementar o Swagger nesta API.

Pegue o projeto aqui:  Aspn_Carter.zip (sem as referências)

"Quando eu disse: O meu pé vacila; a tua benignidade, Senhor, me susteve."
Salmos 94:18

Referências:


José Carlos Macoratti