Sitemap

Criando uma API .NET com Minimal Api (atualizado em 2025)

10 min readOct 30, 2025
Criando uma API .NET com Minimal Api (atualizado em 2025)

Em 2019, escrevi um artigo (Criando a primeira API com .NET Core. | by Marcio Nizzola | Medium) que teve em torno de 10.000 visualizações, mas que ficou obsoleto com o lançamento de novas features do C Sharp.

Na época, focamos em controllers tradicionais para construir APIs no .NET Core. Mas o ecossistema evoluiu rapidamente! Hoje, com o .NET 9 (e o quase-lançado .NET 10), a recomendação é usar Minimal APIs (saiba mais aqui O que são Minimal API´s no .NET 6? | by Marcio Nizzola | Medium) para projetos simples e leves. Elas reduzem o boilerplate, eliminam a necessidade de controllers e tornam o código mais conciso, sem sacrificar a funcionalidade.

Se você é novo no mundo das APIs (Application Programming Interface), lembre-se: uma API é uma ponte segura entre sistemas. Ela permite que apps desktop, web, mobile ou IoT interajam com sua aplicação sem expor diretamente o banco de dados, respeitando limitações de SO ou tecnologias.

Vamos criar nossa primeira API moderna usando .NET 9 ou 10 (preview). Usaremos o Visual Studio 2022 (ou o VS Code com CLI), Entity Framework Core para o banco de dados e faremos os para testes. No final, teremos uma API CRUD básica para gerenciar clientes.

Passo 1: Criando o Projeto

Abra o Visual Studio e clique em “Create a new project”. No menu esquerdo, selecione “.NET” e escolha “ASP.NET Core Web API”. Dê um nome ao projeto, como “FirstApiMinimal”, selecione a pasta de salvamento e clique em “Next”.

Press enter or click to view image in full size

Na tela de configuração:

  • Escolha “.NET 9.0 (Long Term Support)” como framework, caso queira se aventurar no Preview pode escolher .NET 10 preview também (até a publicação ainda não tinha sido lançado o .NET 10).
  • Desmarque “Use controllers” (isso é chave para Minimal APIs!).
  • Deixe “Enable OpenAPI support” por enquanto, caso ainda queira adicionar Swagger ele foi removido e terá que ser adicionado à parte como pacote Nuget.
  • Você pode até desmarcar “Configure for HTTPS” para simplicidade local.
Press enter or click to view image in full size

Clique em “Create”. O Visual Studio gerará o projeto com um Program.cs minimalista — o coração da nossa API.

Estrutura inicial:

Press enter or click to view image in full size
  • Program.cs: Onde configuramos serviços e endpoints.
  • appsettings.json: Para configurações, como a string de conexão do banco.

Passo 2: Adicionando o Modelo e o Contexto de Dados

Crie pastas para organização: clique com o botão direito no projeto > Add > New Folder. Crie “Models” e “Data”.

Na pasta Models, adicione uma nova classe (Add > Class) chamada Customer.cs (será o nosso cliente) :

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace FirstMinimalApi.Models;

[Table("Customers")] // Anotação para nome da tabela (vamos usar isso depois)
public class Customer
{
[Key]
public int Id { get; set; }

[Required]
[MaxLength(50, ErrorMessage = "O nome deve ter no máximo 100 caracteres.")]
public string Name { get; set; } = string.Empty;

[Required]
[MaxLength(18, ErrorMessage = "O CPF deve ter no máximo 14 caracteres.")]
public string DocumentNumber { get; set; } = string.Empty;

[Required]
[EmailAddress(ErrorMessage = "O email fornecido não é válido.")]
public string Email { get; set; } = string.Empty;

[Required]
[DataType(DataType.Date)]
public DateTime BirthDate { get; set; }

public DateTime CreateDate { get; set; } = DateTime.Now;
}

Aqui, usamos Data Annotations do .NET para validar campos:

  • [Key]: Define o Id como chave primária.
  • [Required] e [MaxLength]: Validações básicas.
  • [Table(“Customers”)]: Garante que a tabela no banco se chame “Clientes” (padrão seria “Cliente”).

Passo 2: Limpar o program.cs

O template do .NET traz um exemplo de uma api mínima com uma simulação de previsão do tempo, limpe todo o program.cs deixando-o assim:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}

app.UseHttpsRedirection();

app.Run();

Na pasta Data, adicione uma classe AppDbContext.cs:

using Microsoft.EntityFrameworkCore;
using PrimeiraApiMinimal.Models;

namespace PrimeiraApiMinimal.Data;

public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }

public DbSet<Cliente> Clientes { get; set; }
}

Passo 3: Agora é que a mágica acontece

Vá até a janela “Solution Explorer” e com o botão direito clique sobre o nome do projeto, fazendo com que o menu flutuante apareça, escolha as opções: Add > New Scaffolded Item

Press enter or click to view image in full size

Na janela que abre, podemos criar automaticamente, baseados numa classe através do processo de “Scaffolding” tudo que é necessário para fazer endpoints “Crud” automaticamente.

  • Model Class : é a classe do modelo, no nosso caso “Customer”.
  • Endpoint Class : é a classe que deverá ser criada para os endpoints, aperte o botão “+” para criar uma nova e especifique o nome.
  • DbContext class: é a classe do contexto, é onde o Entity Framework irá configurar as entidades do banco de dados, e será utilizada para manipulá-lo.
  • Database Provider: é o tipo de banco de dados que você irá utilizar.
Press enter or click to view image in full size

Pronto, aperte o botão “Add” e veja a mágica acontecer ! Serão criados dois novos arquivos “AppDbContext.cs” que é a nossa classe do contexto, e “CustomerEndpoints.cs” que contém os endpoints criados, utilizando o conceito de “Minimal Api”.

Vamos ver então o que tem dentro da classe “CustomerEndpoints.cs”, nela estão os endpoints com os métodos Get, Post, Put e Delete, utilizando Entity Framework para persistir as informações no banco de dados !

Se você nunca ouviu falar de Minimal API, neste post entro em detalhe de cada implementação: https://marcionizzola.medium.com/o-que-s%C3%A3o-minimal-api-s-no-net-6-45e3d292acc9

using Microsoft.EntityFrameworkCore;
using FirstMinimalApi.Models;
using Microsoft.AspNetCore.Http.HttpResults;
namespace FirstMinimalApi;

public static class CustomerEndpoints
{
public static void MapCustomerEndpoints (this IEndpointRouteBuilder routes)
{
var group = routes.MapGroup("/api/Customer").WithTags(nameof(Customer));

group.MapGet("/", async (AppDbContext db) =>
{
return await db.Customer.ToListAsync();
})
.WithName("GetAllCustomers");

group.MapGet("/{id}", async Task<Results<Ok<Customer>, NotFound>> (int id, AppDbContext db) =>
{
return await db.Customer.AsNoTracking()
.FirstOrDefaultAsync(model => model.Id == id)
is Customer model
? TypedResults.Ok(model)
: TypedResults.NotFound();
})
.WithName("GetCustomerById");

group.MapPut("/{id}", async Task<Results<Ok, NotFound>> (int id, Customer customer, AppDbContext db) =>
{
var affected = await db.Customer
.Where(model => model.Id == id)
.ExecuteUpdateAsync(setters => setters
.SetProperty(m => m.Id, customer.Id)
.SetProperty(m => m.Name, customer.Name)
.SetProperty(m => m.DocumentNumber, customer.DocumentNumber)
.SetProperty(m => m.Email, customer.Email)
.SetProperty(m => m.BirthDate, customer.BirthDate)
.SetProperty(m => m.CreateDate, customer.CreateDate)
);
return affected == 1 ? TypedResults.Ok() : TypedResults.NotFound();
})
.WithName("UpdateCustomer");

group.MapPost("/", async (Customer customer, AppDbContext db) =>
{
db.Customer.Add(customer);
await db.SaveChangesAsync();
return TypedResults.Created($"/api/Customer/{customer.Id}",customer);
})
.WithName("CreateCustomer");

group.MapDelete("/{id}", async Task<Results<Ok, NotFound>> (int id, AppDbContext db) =>
{
var affected = await db.Customer
.Where(model => model.Id == id)
.ExecuteDeleteAsync();
return affected == 1 ? TypedResults.Ok() : TypedResults.NotFound();
})
.WithName("DeleteCustomer");
}
}

Vamos agora ver o arquivo “AppDbContext.cs”, nele está montado o contexto do banco de dados:

using Microsoft.EntityFrameworkCore;

public class AppDbContext : DbContext
{
public AppDbContext (DbContextOptions<AppDbContext> options)
: base(options)
{
}

public DbSet<FirstMinimalApi.Models.Customer> Customer { get; set; } = default!;
}

Esse é o DbContext do Entity Framework Core (EF Core). Ele mapeia nossa entidade Customer(Cliente) para o banco de dados.

Passo 3: Configurando o Banco de Dados com Code-First e Migrations

Instale o pacote do EF Core via NuGet:

  • Clique com o botão direito no projeto > Manage NuGet Packages.
  • Busque e instale: Microsoft.EntityFrameworkCore.Tools (para migrations).

Abra o appsettings.json e veja que foi adicionada já a string de conexão:

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"AppDbContext": "Server=(localdb)\\mssqllocaldb;Database=AppDbContext-4c24acbd-b158-41f2-a324-133fb40f8d2b;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}

Quando o Scaffolding foi feito, ele automaticamente incluiu novos comandos no “Program.cs”, ficando desta forma agora:

using Microsoft.EntityFrameworkCore;
using FirstMinimalApi;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("AppDbContext") ??
throw new InvalidOperationException("Connection string 'AppDbContext' not found.")));

// Add services to the container.
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}

app.UseHttpsRedirection();

app.MapCustomerEndpoints();

app.Run();

Agora, crie as migrations via Package Manager Console (Tools > NuGet Package Manager > Package Manager Console):

Press enter or click to view image in full size
  1. execute o comando para criar a migração inicial: Add-Migration InitialCreate
  2. Script-Migration — Gera o SQL para revisão. Se quiser alterar o nome da tabela para “Clientes”, edite o arquivo na pasta Migrations (altere modelBuilder.Entity<Cliente>().ToTable(“Clientes”); se necessário).
  3. Update-Database — Aplica a migration e cria o banco.

Pronto! O banco PrimeiraApiDb foi criado no LocalDB.

Passo 4: Nem tudo é perfeito

Tem um detalhe no Scaffolding que foi feito, há um bug que eu vi, onde caso nós executemos o método “Put” que faz a alteração, ele considera atualizar o Id, mas o campo Id é chave primária, portanto não pode ser alterado, e vai dar um erro, sendo assim, remova ou comente a linha para funcionar corretamente como eu fiz abaixo.

Press enter or click to view image in full size
no processo de scaffold há um bug, comente esta linha

Passo 5: Testando a API

Agora vamos testar? Para o teste vamos utilizar o arquivo “FirstMinimalApi.http” que já veio no nosso template, mas substitua-o pelo novo que foi adaptado aos novos endpoint:

@FirstMinimalApi_HostAddress = http://localhost:5226

### Get all customers
GET {{FirstMinimalApi_HostAddress}}/api/Customer
Accept: application/json

### Get customer by ID
GET {{FirstMinimalApi_HostAddress}}/api/Customer/1
Accept: application/json

### Create new customer
POST {{FirstMinimalApi_HostAddress}}/api/Customer
Content-Type: application/json

{
"name": "John Doe",
"documentNumber": "123.456.789-00",
"email": "john.doe@example.com",
"birthDate": "1990-01-01"
}

### Update customer
PUT {{FirstMinimalApi_HostAddress}}/api/Customer/1
Content-Type: application/json

{
"id": 1,
"name": "John Doe Updated",
"documentNumber": "123.456.789-00",
"email": "john.updated@example.com",
"birthDate": "1990-01-01",
"createDate": "2025-10-07T10:00:00"
}

### Delete customer
DELETE {{FirstMinimalApi_HostAddress}}/api/Customer/1

Se nunca viu estes tipos de teste, veja meu post antigo: Esqueça o Postman, use o VSCode para testar API´S ! | by Marcio Nizzola | Medium neste o Visual Studio agora também suporta arquivos .http, proporcionando uma nova forma de testar api´s.

Com este código http, podemos agora testar, o Visual Studio permite que executemos as chamadas utilizando o arquivo .http, veja o exemplo abaixo

Press enter or click to view image in full size

Podemos ver no lado esquerdo da imagem que há um comando “Send Request” abaixo de cada separador “###”, que se executado, irá chamar a api e exibir no lado direito o resultado. Neste exemplo foi clicado no método Get que resultou num código 200, indicando o sucesso !

Novidade: O .NET 10 tem validação nativa em Minimal ?

Sim, uma das melhorias implementadas na versão 10 é a validação de requisições, onde caso um campo obrigatório não for fornecido, ou um campo tiver um tamanho diferente da especificação, será feita uma validação pelo próprio endpoint.

Basta acrescentar a linha em destaque no program.cs:

Veja o exemplo abaixo onde retirei o campo “name” que é obrigatório, gerando um erro de validação:

Press enter or click to view image in full size

Pronto, com esse exemplo você pode começar a criar suas api´s utilizando os conceitos de Minimal Api.

Há muito mais coisas que você pode fazer para melhorá-las, seguem alguns dos meus post´s !

Gostou do artigo? clique no ícone👏, compartilhe com os amigos e me siga para ver as próximas publicações !! Quer ver mais conteúdos, acesse minhas redes através do Linktree: https://linktree.com/nizzola

Saiba mais sobre Minimal API

--

--

Marcio Nizzola
Marcio Nizzola

Written by Marcio Nizzola

Microsoft MVP | Master Software Architect na CI&T | Prof. da Etec Itu | Membro Fundador da Comunidade Itu Developers.

No responses yet