Minimal API .NET: o que é isso?
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.
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”.
E sem esquecer de selecionar a versão 6.0 do .NET Core.
Repare na estrutura do projeto criado:
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?
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”.
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:
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:
- Documentação da Microsoft - API Mínima Core
- Formação ASP.NET Core REST APIs na Alura
- Curso APIs Rest com Asp.NET Core 2.1 Parte 3: padronizando a API na Alura
Você pode baixar o zip ou acessar o link do repositório no GitHub!