Minimal API .NET: o que é isso?

Minimal API .NET: o que é isso?
André Bessa
André Bessa

Compartilhe

Imagine conseguir escrever o mínimo necessário para ter uma Web API inteira, com recursos de acesso a dados e documentada com Swagger. Será que isso é possível? Neste artigo falaremos das Minimal APIs, um novo recurso apresentado oficialmente à comunidade de desenvolvedores junto ao .NET 6.0 e que nos permite esse tipo de simplificação.

Quando estamos criando um serviço web usando a plataforma .NET, muito provavelmente usaremos os recursos das Web APIs dentre as opções disponíveis, porque elas já estruturam um backend para desenvolvermos usando C#. Apesar da estrutura de um projeto deste tipo ter evoluído com o passar do tempo, ainda ficamos dependentes de muitos recursos e configurações.

E aí vamos conferir como as Minimal APIs realmente funcionam ? 😉

O que é uma Minimal API?

Com a chegada do .NET 6, a Microsoft disponibilizou o recurso das Minimal APIs, que foram pensadas para permitir a criação de APIs HTTP que utilizem menos recursos, sendo uma ótima solução para implementação de microsserviços e aplicativos que consumam o mínimo de dependências do ASP .NET Core, por exemplo.

Então, que tal criar uma API de cadastro de pessoas escrevendo o mínimo de linhas de código o possível? Para isso teremos uma lista em memória e como pré-requisitos, usaremos o NET 6 e o Visual Studio Community 2022, mas fique a vontade para usar outra IDE que seja de sua escolha como o VS Code por exemplo.

Na imagem vemos a tela do Visual Studio Installer, destacando a opção ASP.NET and web development.

Com o Visual Studio Community 2022 aberto, crie um novo projeto ASP.NET Core vazio, como na imagem abaixo:

<> projeto ASP.NET Core Vazio.](assets/minimal-api-net-o-que-e-isso/imagem2.png)

Ah, vamos definir também um nome para nosso projeto, que será “Alura.MinimalAPI”.

Na imagem vemos a tela do Visual Studio 2022, com a opção do nome do projeto destacada.

E sem esquecer de selecionar a versão 6.0 do .NET Core.

Na imagem vemos a tela do Visual Studio 2022, com  a opção do framework .NET 6.0 destacada.

Repare na estrutura do projeto criado:

Na imagem vemos a tela do Visual Studio 2022, com a opção do gerenciador de soluções destacado.

Dessa forma, já temos uma API funcional. Agora execute o projeto clicando no botão ”Run” no menu superior do Visual Studio Community. No navegador padrão será exibida a página principal encontrada em “localhost:7274” e será exibida a mensagem “Hello World”.

Bem bacana! 😉 Mas queremos desenvolver mais do que um “Hello world”, certo? Vamos criar uma solução que funcione em memória, uma lista de pessoas, e realizar as operações de inserção, atualização, remoção e listagem.

Em nosso projeto de exemplo adicionamos um diretório Model e vamos criar as classes Pessoa e RepositorioDePessoas.

O código de Pessoa será o seguinte:

namespace Alura.MinimalAPI.Alura.MinimalAPI.Model
{
    public class Pessoa
    {
        public Pessoa()
        {
               Identificador = Guid.NewGuid();
        }
        public Guid Identificador { get; set; }
        public string Nome { get; set; } = string.Empty;
        public string CPF { get; set; } = string.Empty;
        public string Email { get; set; } = string.Empty;
    }
}

Com base nesta classe, criamos uma outra com algumas funcionalidades para manipular uma lista de pessoas em memória, a RepositorioDePessoa. Vamos usar este recurso para simular uma base de dados. O código dela será:

namespace Alura.MinimalAPI.Alura.MinimalAPI.Model
{
    public class RepositorioDePessoas
    {   
        public RepositorioDePessoas(bool dados)
        {
            if (dados)
            {
                CriarDadosEmMemoria();
            }
            else
            {
                ListaPessoas = new List<Pessoa>();
            }
        }

        private void CriarDadosEmMemoria()
        {

            this.ListaPessoas = new List<Pessoa>()
            {
                new Pessoa()
                {
                    Nome = "André Silva",
                    CPF = "123456789-12",
                    Email ="[email protected]"
                },
                new Pessoa()
                {
                    Nome = "Pedro Malazartes",
                    CPF = "182993692-12",                    
                    Email ="[email protected]"
                },
                new Pessoa()
                {
                    Nome = "Maria Joaquina",
                    CPF = "987351984-12",                    
                    Email ="[email protected]"
                }
            };
        }

        public List<Pessoa> ListaPessoas { get; set; }

        public Pessoa AdicionarPessoas(Pessoa p)
        {
            ListaPessoas.Add(p);
            return p;
        }

        public bool RemoverPessoas(string  cpf)
        {
            var pessoaTemp = (from pessoa in this.ListaPessoas
                              where pessoa.CPF == cpf
                               select pessoa).SingleOrDefault();
            if (pessoaTemp == null)
            {
                return false;
            }
            var removido = ListaPessoas.Remove(pessoaTemp);            
            return removido;
        }

        public List<Pessoa> SelecionarPessoas()
        {
            return this.ListaPessoas;
        }

        public Pessoa SelecionarPessoa(string cpf)
        {
             var pessoaTemp = (from pessoa in ListaPessoas
                    where pessoa.CPF == cpf
                    select pessoa).SingleOrDefault();
            if (pessoaTemp==null)
            {
                return new Pessoa();
            }
            return pessoaTemp;
        }

        public bool AtualizarPessoas(Pessoa p)
        {
            var pessoaTemp = (from pessoa in this.ListaPessoas
                              where pessoa.CPF == p.CPF
                              select pessoa).SingleOrDefault();
            if (pessoaTemp == null)
            {
                return false;
            }

            pessoaTemp.Identificador = p.Identificador;
            pessoaTemp.Nome = p.Nome;

            return true;
        }

    }
}

Repare que nesses códigos de classes não temos aqueles using, responsáveis pela importação de bibliotecas padrão. Para onde eles foram? Onde estão as bibliotecas?

Banner de divulgação da Imersão IA da Alura em colaboração com o Google. Mergulhe em Inteligência artificial com a Alura e o Google. Serão cinco aulas gratuitas para você aprender a usar IA na prática e desenvolver habilidades essenciais para o mercado de trabalho. Inscreva-se gratuitamente agora!

Global usings

A plataforma .NET permite agora a configuração dos nossos projetos com as global usings. Com elas temos um trecho específico no código onde ficarão definidas as importações das bibliotecas básicas que usarmos. Na criação do projeto, a opção das global usings já estará habilitada no arquivo “.csproject”.

Na imagem é mostrado o conteúdo do arquivo .csproject e exibida a configuração que habilita a utilização de global usings.

Portanto, as seguintes bibliotecas serão configuradas de maneira implícita no projeto:

System.Net.Http.Json
Microsoft.AspNetCore.Builder
Microsoft.AspNetCore.Hosting
Microsoft.AspNetCore.Http
Microsoft.AspNetCore.Routing
Microsoft.Extensions.Configuration
Microsoft.Extensions.DependencyInjection
Microsoft.Extensions.Hosting
Microsoft.Extensions.Logging

e as bibliotecas básicas:

System.Collections.Generic
System.IO
System.Linq
System.Net.Http
System.Threading
System.Threading.Task

Classe Program.CS

De volta ao projeto da minimal API, vamos configurá-lo para trabalhar com o Swagger. Como criamos um projeto vazio, adicione o pacote via NuGet, acessando pelo menu superior > “Ferramentas”> “Gerenciador de pacotes do Nuget” > “Gerenciador de pacotes do NuGet para essa solução…”, como na imagem abaixo:

Na imagem é mostrada a tela do NuGet  para adição no projeto da biblioteca `Swashbuckle.AspNetCore` do Swagger.

Agora vamos à definição de todo o código da nossa classe Program.CS:

using Alura.MinimalAPI.Alura.MinimalAPI.Model;

var builder = WebApplication.CreateBuilder(args);

//Habilitando o swagger
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

//instanciando o repositório em memória.
var repositorio = new RepositorioDePessoas(true);

app.UseSwagger();// Ativando o Swagger

// Endpoints da solução
app.MapGet("/", () => "Hello World!");

// Listar todas as pessoas.
app.MapGet("/ListaPessoas", () => {
    return repositorio.SelecionarPessoas();        
    });

//Buscar pessoa pelo CPF.
app.MapGet("/ListaPessoas/{cpf}", (string cpf) => {
    return repositorio.SelecionarPessoa(cpf);
});

//Adicionar pessoa.
app.MapPost("/ListaPessoas/adicionar", (Pessoa pessoa) => {
    return repositorio.AdicionarPessoas(pessoa);
});

//Atualizar pessoa.
app.MapPut("/ListaPessoas/atualizar", (Pessoa pessoa) => {
    return repositorio.AtualizarPessoas(pessoa);
});

//Remover pessoa.
app.MapDelete("/ListaPessoas/remover", (string cpf) => {
    return repositorio.RemoverPessoas(cpf);
});

app.UseSwaggerUI();// Ativando a interface Swagger

app.Run();

Repare como nossa classe está bem mais enxuta agora que criamos um serviço web com 50 linhas e endpoints documentados usando Swagger. A escrita de um endpoint também está mais simples devido ao uso de uma expressão lambda. Por exemplo:

app.MapPost("/ListaPessoas/adicionar", (Pessoa pessoa) => {
    return repositorio.AdicionarPessoas(pessoa);
});

O resultado obtido pode ser observado executando o projeto no Visual Studio Community 2022 e acessando a url https://localhost:7274/swagger/index.html.

Minimalismo na programação

A ideia de simplificar a escrita de códigos tem se tornado mais presente na rotina de desenvolvimento, se fazendo notar em outras linguagens mais modernas, como Python. Existe uma tendência ao minimalismo, ou seja, a abrir mão do que não for essencial para o funcionamento de nossos softwares, inclusive no universo .NET.

Mas que objetivos a Microsoft tenta atingir com uma solução de API mínima? Vamos elencar alguns deles a seguir:

  • Para os iniciantes em programação, diminuir a complexidade do código;
  • Reduzir a necessidade de utilizar alguns recursos que podem não ser essenciais para uma solução ASP.NET como controllers, roteamento, filtros, etc;
  • Adotar o minimalismo a nível de API, buscando maior facilidade de entendimento do código que está sendo gerado.;
  • Pensar em aplicações que sejam ao mesmo tempo simples e escaláveis, ou seja, tenham um código legível, além da capacidade de expandir o armazenamento de dados ou atendimento de usuários.

Conclusão

A plataforma .NET tem evoluído a passos largos nos últimos anos e incorporou diversos recursos para tornar a plataforma de desenvolvimento mais dinâmica e simples, beneficiando pessoas novas na área sem deixar de agradar as mais experientes.

Nesse sentido, simplificar o desenvolvimento de uma API ajuda bastante e reflete a intenção da Microsoft de ouvir as demandas da comunidade, oferecendo soluções cada vez mais atraentes para todos os públicos.

Ficamos então com o lema minimalista “Menos é mais”. Até a próxima! 😉

Para conhecer mais sobre programação com .NET e mergulhar mais fundo em tecnologia, veja:

Você pode baixar o zip ou acessar o link do repositório no GitHub!

André Bessa
André Bessa

Eu sou programador e instrutor de programação usando C# e .NET. Formado em Sistemas de Informação. já programei usando Java, PHP,C#, PostgreSQL e MySQL, além de já ter atuado com suporte também. Buscando sempre aprender mais sobre tecnologias.Hobbies são gibis e séries.

Veja outros artigos sobre Programação