O ASP.NET Core oferece diferentes abordagens para desenvolver APIs REST com C#. Entre as principais opções estão as Minimal APIs e as APIs baseadas em Controllers. Ambas permitem construir serviços HTTP modernos, implementar operações CRUD, integrar bancos de dados, aplicar autenticação e autorização e disponibilizar funcionalidades para aplicações web, mobile e outros sistemas.
Apesar de compartilharem muitos recursos, essas abordagens apresentam diferenças importantes na organização do código, na configuração dos endpoints, na validação de dados e na manutenção da aplicação.
Com a evolução do .NET, as Minimal APIs ganharam recursos que permitem utilizá-las também em aplicações mais estruturadas, deixando de ser uma alternativa restrita a pequenos serviços. Por outro lado, os Controllers continuam sendo uma escolha relevante para sistemas empresariais que precisam de convenções estabelecidas, recursos específicos do MVC e uma organização baseada em classes e ações.
Mas, afinal, qual abordagem vale mais a pena utilizar em um projeto novo? E será que compensa migrar uma API existente baseada em Controllers para Minimal APIs?
Neste artigo, vamos comparar as duas alternativas, apresentar exemplos práticos em C# e analisar os principais critérios que devem orientar essa decisão.
As Minimal APIs são uma abordagem para criar APIs HTTP com menos código estrutural. Em vez de definir uma classe Controller para agrupar as operações de um recurso, podemos mapear os endpoints diretamente na aplicação ou em módulos separados.
A proposta é reduzir o código necessário para configurar rotas e implementar o tratamento das requisições, sem abrir mão de recursos importantes como injeção de dependência, autenticação, autorização, filtros e documentação OpenAPI.
As Minimal APIs são especialmente interessantes quando queremos desenvolver serviços HTTP com uma estrutura simples e explícita.
Considere o exemplo de uma API responsável por consultar produtos.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/api/products", () =>
{
var products = new[]
{
new { Id = 1, Name = "Teclado", Price = 49.90m },
new { Id = 2, Name = "Mouse", Price = 29.90m }
};
return Results.Ok(products);
});
app.Run();
Nesse exemplo, criamos um endpoint HTTP GET que retorna uma lista de produtos.
O método MapGet associa uma rota a um handler, responsável por processar a requisição e produzir a resposta.
Não precisamos criar uma classe Controller, definir um método de ação ou configurar atributos de roteamento. O endpoint é registrado diretamente na aplicação.
Essa simplicidade facilita a implementação de endpoints pequenos e permite visualizar rapidamente quais rotas estão disponíveis.
Entretanto, é importante compreender que Minimal APIs não significa necessariamente concentrar toda a aplicação em um único arquivo.
Em projetos maiores, podemos separar os endpoints em classes, organizar funcionalidades por módulos e delegar o processamento das requisições a serviços de aplicação.
A abordagem permite começar de maneira simples e evoluir a estrutura conforme as necessidades do sistema.
Os Controllers representam uma abordagem tradicional para desenvolver APIs com ASP.NET Core.
Nessa estrutura, agrupamos operações relacionadas em classes que herdam de ControllerBase. Cada método de ação representa uma operação que pode responder a uma requisição HTTP.
Essa organização facilita a separação das responsabilidades por recurso, como clientes, produtos, pedidos e pagamentos.
Veja como ficaria o mesmo exemplo utilizando Controllers.
Primeiro, configuramos o suporte a Controllers no arquivo Program.cs:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();
Em seguida, criamos o Controller responsável pelos produtos:
using Microsoft.AspNetCore.Mvc;
namespace BackstageTech.Api.Controllers;
[ApiController]
[Route("api/products")]
public class ProductsController : ControllerBase
{
[HttpGet]
public IActionResult GetAll()
{
var products = new[]
{
new { Id = 1, Name = "Teclado", Price = 49.90m },
new { Id = 2, Name = "Mouse", Price = 29.90m }
};
return Ok(products);
}
}
Embora o resultado seja semelhante ao exemplo anterior, a organização é diferente.
O Controller agrupa as operações relacionadas a produtos. O atributo [Route] define a rota-base, enquanto [HttpGet] identifica o método que responderá às requisições GET.
Além disso, o atributo [ApiController] habilita comportamentos específicos para APIs, incluindo recursos de inferência de parâmetros e respostas automáticas para determinados erros de validação do modelo.
Essa abordagem é familiar para muitos desenvolvedores que trabalham com aplicações empresariais em .NET.
Também oferece uma estrutura conveniente para projetos que utilizam recursos específicos do ASP.NET Core MVC.
As duas abordagens conseguem atender a muitos dos mesmos requisitos. A principal diferença não está na possibilidade de construir uma API REST completa, mas na maneira como organizamos e implementamos seus endpoints.
Vamos comparar os aspectos mais importantes.
| Critério | Minimal APIs | Controllers |
|---|---|---|
| Organização inicial | Mapeamento direto de endpoints | Classes que agrupam ações |
| Código estrutural | Geralmente menor | Geralmente maior |
| Roteamento | Métodos como MapGet, MapPost e MapPut |
Atributos como [HttpGet] e [HttpPost] |
| Injeção de dependência | Suportada diretamente nos handlers | Suportada por construtores e outros mecanismos de DI |
| Validação | Suporta recursos próprios e integrações configuráveis | Integração consolidada com o pipeline MVC e [ApiController] |
| Filtros | Suporta endpoint filters | Suporta filtros MVC, incluindo filtros de ação |
| Autorização | Suporta políticas e metadados de autorização | Suporta políticas e atributos de autorização |
| Documentação OpenAPI | Suportada | Suportada |
| Organização de projetos grandes | Exige uma estrutura de módulos bem planejada | Oferece agrupamento natural por Controllers |
| Recursos específicos do MVC | Não oferece diretamente todos os recursos do MVC | Oferece recursos específicos do framework MVC |
| Adequação a novos projetos | Excelente opção para APIs HTTP modernas | Continua sendo uma opção válida |
| Migração de sistemas existentes | Pode exigir mudanças estruturais | Adequado para manter a arquitetura existente |
A tabela apresenta tendências gerais, não regras absolutas.
Uma aplicação com Minimal APIs pode ter uma excelente separação de responsabilidades, assim como uma API baseada em Controllers pode se tornar difícil de manter quando suas classes acumulam responsabilidades excessivas.
O resultado depende da arquitetura adotada, das convenções do projeto e da disciplina da equipe.
Uma das principais vantagens das Minimal APIs é a redução do código necessário para registrar endpoints.
Em uma aplicação pequena, podemos implementar várias operações HTTP sem criar uma classe para cada recurso.
Por exemplo:
app.MapGet("/api/products", () => Results.Ok("Listar produtos"));
app.MapGet("/api/products/{id:int}", (int id) =>
Results.Ok($"Produto {id}"));
app.MapPost("/api/products", () => Results.Created("/api/products/1", null));
app.MapDelete("/api/products/{id:int}", (int id) =>
Results.NoContent());
O exemplo demonstra como diferentes operações podem ser registradas diretamente na aplicação.
Entretanto, a redução de código estrutural não significa que a lógica de negócio deva ficar dentro dos handlers.
Imagine que um endpoint precise verificar a disponibilidade de um produto, calcular preços, validar regras comerciais e registrar uma movimentação de estoque.
Colocar tudo isso diretamente no handler tornaria o código difícil de testar e manter.
Uma solução melhor é manter o endpoint responsável pela interação HTTP e delegar o processamento a um serviço apropriado.
Essa separação permite aproveitar a simplicidade das Minimal APIs sem comprometer a arquitetura.
Nos Controllers, parte dessa organização já acontece naturalmente por meio de classes e métodos de ação. Mesmo assim, também é necessário evitar que os Controllers acumulem regras de negócio.
A performance costuma aparecer entre os argumentos favoráveis às Minimal APIs.
A Microsoft apresenta essa abordagem como uma alternativa simplificada e de alto desempenho para a construção de APIs HTTP.
Isso não significa, porém, que qualquer aplicação baseada em Minimal APIs será automaticamente mais rápida do que uma aplicação equivalente baseada em Controllers.
O desempenho depende de diversos fatores, incluindo:
Complexidade das operações executadas.
Consultas ao banco de dados.
Serialização e desserialização de JSON.
Processamento de autenticação e autorização.
Uso de rede e serviços externos.
Alocação de memória.
Configuração do servidor.
Implementação dos próprios endpoints.
Em uma API que executa consultas complexas no banco de dados ou depende de vários serviços externos, a diferença entre as duas abordagens pode representar apenas uma pequena parcela do tempo total de resposta.
Por outro lado, serviços que executam operações HTTP muito simples podem se beneficiar de diferenças de overhead.
Para descobrir se essa diferença é relevante no seu cenário, o ideal é realizar testes de carga com implementações equivalentes.
Compare o tempo de resposta, o throughput, o consumo de memória e a utilização de CPU sob condições controladas.
Também é importante manter iguais os demais componentes das duas implementações.
Não seria uma comparação justa colocar uma Minimal API com acesso direto a uma coleção em memória contra um Controller que executa várias operações no banco de dados.
A conclusão é simples: performance deve ser avaliada com métricas do projeto, e não apenas com base na escolha entre Minimal APIs e Controllers.
Aqui encontramos uma das diferenças mais importantes para projetos de médio e grande porte.
Em uma Minimal API pequena, registrar os endpoints diretamente no Program.cs pode ser suficiente.
Entretanto, à medida que a aplicação cresce, esse arquivo pode acumular dezenas ou centenas de definições de rotas.
Isso prejudica a legibilidade e dificulta a identificação das responsabilidades de cada funcionalidade.
A solução não é necessariamente abandonar as Minimal APIs, mas estruturar os endpoints em módulos separados.
Por exemplo, podemos criar uma classe ProductEndpoints:
using Microsoft.AspNetCore.Mvc;
namespace BackstageTech.Api.Endpoints;
public static class ProductEndpoints
{
public static IEndpointRouteBuilder MapProductEndpoints(
this IEndpointRouteBuilder endpoints)
{
var group = endpoints.MapGroup("/api/products");
group.MapGet("/", () =>
{
return Results.Ok("Lista de produtos");
});
group.MapGet("/{id:int}", (int id) =>
{
return Results.Ok($"Produto {id}");
});
return endpoints;
}
}
No arquivo Program.cs, registramos o módulo:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapProductEndpoints();
app.Run();
Com essa organização, as rotas relacionadas a produtos ficam concentradas em um módulo próprio.
Podemos aplicar o mesmo padrão para clientes, pedidos, pagamentos e outras áreas da aplicação.
O uso de MapGroup também permite organizar endpoints que compartilham um prefixo de rota e aplicar configurações comuns, como metadados, filtros e políticas de autorização.
É importante observar que esse exemplo é apenas uma demonstração de organização. Em uma aplicação real, os handlers devem delegar o processamento a serviços apropriados e utilizar os modelos de entrada e saída necessários.
Nos Controllers, a separação por classes já faz parte da estrutura natural do framework.
Podemos criar um ProductsController, um CustomersController e um OrdersController, mantendo cada conjunto de ações isolado.
Por esse motivo, equipes que já trabalham com MVC podem considerar os Controllers mais familiares.
Ainda assim, as duas abordagens permitem construir aplicações modulares. A escolha depende de qual estrutura atende melhor às necessidades da equipe.
A injeção de dependência é um recurso fundamental no desenvolvimento moderno com .NET.
Ela permite que os componentes recebam suas dependências por meio do container de serviços, reduzindo o acoplamento e facilitando os testes.
Tanto Minimal APIs quanto Controllers integram-se ao sistema de injeção de dependência do ASP.NET Core.
Nas Minimal APIs, um serviço registrado pode ser recebido diretamente como parâmetro do handler.
Considere um serviço responsável por consultar produtos:
public interface IProductService
{
Task<IReadOnlyList<string>> GetAllAsync(
CancellationToken cancellationToken);
}
O endpoint pode receber essa dependência diretamente:
app.MapGet(
"/api/products",
async (
IProductService productService,
CancellationToken cancellationToken) =>
{
var products = await productService.GetAllAsync(
cancellationToken);
return Results.Ok(products);
});
Para que o exemplo funcione, precisamos registrar uma implementação concreta de IProductService no container de dependências.
A resolução do serviço acontece por meio da infraestrutura do ASP.NET Core.
Em um Controller, normalmente recebemos a mesma dependência pelo construtor:
[ApiController]
[Route("api/products")]
public class ProductsController : ControllerBase
{
private readonly IProductService _productService;
public ProductsController(IProductService productService)
{
_productService = productService;
}
[HttpGet]
public async Task<IActionResult> GetAll(
CancellationToken cancellationToken)
{
var products = await _productService.GetAllAsync(
cancellationToken);
return Ok(products);
}
}
Ambas as implementações permitem manter a lógica de negócio fora da camada HTTP.
A diferença está principalmente na maneira como as dependências são declaradas e recebidas.
Em projetos com muitos serviços, a injeção direta nos handlers pode reduzir código estrutural. Já o uso de construtores nos Controllers torna explícito o conjunto de dependências da classe.
Nenhuma dessas características determina, isoladamente, qual arquitetura será mais fácil de manter.
A validação é um dos pontos que merecem atenção especial na comparação.
Em APIs, não basta receber uma requisição e executar uma operação. É necessário verificar se os dados fornecidos são válidos e se respeitam as regras aplicáveis.
Imagine que precisamos cadastrar um produto com nome e preço.
Podemos definir um modelo de entrada:
using System.ComponentModel.DataAnnotations;
public sealed class CreateProductRequest
{
[Required]
[StringLength(100)]
public string Name { get; init; } = string.Empty;
[Range(0.01, 1000000)]
public decimal Price { get; init; }
}
Esse modelo define restrições para o nome e o preço.
No caso dos Controllers, o atributo [ApiController] integra a validação do modelo ao pipeline MVC e pode produzir automaticamente uma resposta HTTP 400 quando a validação falha.
Nas Minimal APIs, o comportamento depende dos recursos de validação disponíveis na versão utilizada e da configuração da aplicação.
A partir do ASP.NET Core 10, existem recursos de validação integrados às Minimal APIs, incluindo suporte baseado em Data Annotations. Em versões anteriores, o comportamento e as opções disponíveis podem ser diferentes.
Por isso, não é correto afirmar que Minimal APIs não suportam validação automática. É necessário considerar a versão do framework e a forma como a aplicação foi configurada.
Em qualquer uma das abordagens, também precisamos distinguir validação estrutural de validação de negócio.
Verificar se um preço é maior que zero é diferente de verificar se o usuário tem autorização para aplicar determinado desconto.
A segunda regra pertence ao domínio ou à lógica de aplicação e não deve depender exclusivamente dos atributos do modelo HTTP.
Em projetos maiores, é recomendável definir uma estratégia consistente para erros de validação, respostas HTTP e mensagens destinadas aos consumidores da API.
Tanto Minimal APIs quanto Controllers oferecem mecanismos para aplicar regras antes ou depois da execução de determinadas operações.
Entretanto, os mecanismos disponíveis e os pontos de integração não são exatamente os mesmos.
As Minimal APIs oferecem endpoint filters, que permitem executar lógica em torno do processamento de um endpoint.
Eles podem ser úteis para validações específicas, registro de informações e outras preocupações transversais adequadas a esse mecanismo.
Um exemplo simplificado seria:
app.MapGet("/api/products", () =>
{
return Results.Ok("Lista de produtos");
})
.AddEndpointFilter(async (context, next) =>
{
var result = await next(context);
return result;
});
O exemplo demonstra a estrutura de um endpoint filter. Como não acrescenta uma regra de negócio, sua finalidade é apenas ilustrativa.
Em aplicações reais, filtros devem ter uma responsabilidade clara e não devem ser utilizados como substitutos indiscriminados de serviços de aplicação.
Os Controllers podem utilizar diferentes tipos de filtros do MVC, incluindo filtros de autorização, de ação e de exceção, conforme o caso.
Esses recursos permitem implementar comportamentos compartilhados dentro do pipeline MVC.
Aplicações que dependem de recursos específicos desse pipeline podem encontrar nos Controllers uma integração mais direta.
As duas abordagens podem utilizar o sistema de autenticação e autorização do ASP.NET Core.
Por exemplo, uma Minimal API pode exigir uma política de autorização:
app.MapGet("/api/admin/reports", () =>
{
return Results.Ok("Relatórios administrativos");
})
.RequireAuthorization("AdminPolicy");
Para utilizar esse exemplo, a aplicação precisa configurar a autenticação, a autorização e a política AdminPolicy.
Nos Controllers, a autorização também pode ser declarada por meio de atributos, como [Authorize], ou aplicada por políticas configuradas na aplicação.
Portanto, a escolha entre Minimal APIs e Controllers não determina se uma API será segura.
O resultado depende da configuração de autenticação, das políticas de autorização e da aplicação correta dessas regras em todos os endpoints protegidos.
A documentação é essencial para APIs consumidas por outras aplicações e equipes.
Ela facilita a descoberta de endpoints, a compreensão dos parâmetros, a identificação dos formatos de entrada e saída e a integração com ferramentas de desenvolvimento.
Minimal APIs e Controllers podem gerar documentação OpenAPI.
Nas Minimal APIs, podemos declarar metadados e informações sobre os resultados esperados dos endpoints.
Nos Controllers, podemos utilizar atributos e tipos de retorno para descrever as operações.
A qualidade da documentação depende de como os endpoints e seus contratos são definidos.
Em ambas as abordagens, vale a pena documentar corretamente:
Métodos HTTP e rotas.
Parâmetros de entrada.
Modelos de requisição e resposta.
Códigos de status HTTP.
Requisitos de autenticação.
Respostas de erro.
Regras relevantes para os consumidores.
Também é importante distinguir a geração do documento OpenAPI da interface visual utilizada para explorá-lo. A configuração necessária depende da versão do ASP.NET Core e das ferramentas adotadas no projeto.
Se a API fizer parte de uma arquitetura com vários serviços, uma documentação consistente é particularmente importante para reduzir dúvidas durante a integração.
Testar uma API não significa apenas verificar se cada endpoint retorna uma resposta HTTP.
Também precisamos garantir que as regras de negócio funcionem corretamente, que os erros sejam tratados de maneira previsível e que as alterações não quebrem comportamentos existentes.
Tanto Minimal APIs quanto Controllers podem ser testados por meio de testes unitários e testes de integração.
Nas Minimal APIs, a separação dos endpoints em módulos e a delegação da lógica de negócio a serviços ajudam a manter os handlers simples.
Nos Controllers, podemos testar os métodos de ação e verificar o comportamento HTTP, além de realizar testes de integração que exercitam a aplicação.
Em ambos os casos, os testes unitários não substituem os testes de integração.
Um teste unitário pode verificar se determinado serviço aplica corretamente uma regra de negócio. Já um teste de integração pode confirmar se uma requisição HTTP percorre o pipeline da aplicação e produz a resposta esperada.
Para testar o comportamento real dos endpoints, o ASP.NET Core disponibiliza mecanismos de teste de integração, incluindo o WebApplicationFactory no ecossistema de testes de aplicações web.
A decisão entre as duas abordagens deve considerar a estrutura dos testes, a complexidade dos handlers e a facilidade de isolar as regras de negócio.
Não existe uma vantagem absoluta de testabilidade que torne uma das alternativas adequada para todos os cenários.
As Minimal APIs são uma excelente opção quando queremos construir uma API HTTP com uma estrutura enxuta, sem depender de todos os recursos do pipeline MVC.
Considere essa abordagem especialmente nos seguintes cenários.
Se você está iniciando um projeto e não depende de recursos específicos dos Controllers, as Minimal APIs são uma opção natural.
Elas permitem começar com poucos elementos estruturais e evoluir a organização conforme a aplicação cresce.
Microsserviços que expõem um conjunto bem definido de operações HTTP podem se beneficiar da abordagem.
A estrutura facilita a declaração dos endpoints e permite organizar cada funcionalidade em módulos independentes.
Isso não significa que Minimal APIs sejam obrigatórias em microsserviços. A decisão também deve considerar os padrões utilizados pela equipe e as necessidades de integração.
Serviços que oferecem operações específicas, como consultas, notificações ou integração entre sistemas, podem ser bons candidatos.
A quantidade de endpoints, isoladamente, não deve determinar a escolha. Um serviço com poucas rotas pode possuir regras de negócio extremamente complexas.
Se a equipe deseja reduzir o código necessário para declarar endpoints, as Minimal APIs podem ajudar.
O benefício é maior quando a estrutura adotada mantém as rotas legíveis e separa a camada HTTP das regras de negócio.
As Minimal APIs continuam evoluindo e recebem recursos que ampliam suas possibilidades de utilização.
Para novos projetos, vale verificar as funcionalidades disponíveis na versão escolhida do framework antes de optar automaticamente por Controllers.
Embora as Minimal APIs sejam recomendadas pela documentação da Microsoft para novos projetos de APIs HTTP, isso não torna os Controllers obsoletos.
Existem situações em que a abordagem baseada em Controllers continua sendo uma escolha técnica bastante adequada.
Se a aplicação possui uma arquitetura consolidada baseada em Controllers, não existe motivo suficiente para migrar apenas porque outra abordagem está disponível.
A migração pode exigir alterações nos testes, na organização do código, nos mecanismos de validação e na configuração dos endpoints.
Antes de iniciar esse trabalho, é necessário identificar um benefício concreto.
Alguns sistemas utilizam funcionalidades diretamente associadas ao pipeline MVC, como determinados filtros, mecanismos de model binding personalizados ou componentes baseados no modelo de aplicação do MVC.
Nesses casos, os Controllers podem simplificar a implementação.
É importante avaliar os requisitos reais, porque alguns comportamentos podem ser implementados de outras maneiras com Minimal APIs, mas nem sempre com o mesmo esforço.
Se toda a equipe já domina Controllers, adotar outra abordagem sem uma necessidade clara pode aumentar a curva de aprendizagem e introduzir novas convenções.
Por outro lado, se a equipe está iniciando um projeto e deseja aprender os recursos mais recentes do ASP.NET Core, as Minimal APIs merecem consideração.
A decisão deve levar em conta a capacidade da equipe de manter o sistema ao longo do tempo.
Projetos grandes frequentemente possuem padrões internos para organização de Controllers, filtros, validação, logging e tratamento de exceções.
Quando essas convenções estão bem implementadas e atendem às necessidades da aplicação, mantê-las pode ser mais vantajoso do que substituí-las.
Se uma biblioteca interna ou um componente da aplicação depende diretamente de mecanismos do MVC, utilizar Controllers pode reduzir o trabalho necessário para a integração.
Antes de tomar essa decisão, vale confirmar se existe suporte equivalente na abordagem Minimal API e se a mudança realmente oferece benefícios.
Essa é uma questão particularmente importante para desenvolvedores que trabalham com arquiteturas em camadas, Clean Architecture ou outros modelos que procuram separar responsabilidades.
A boa notícia é que não precisamos abandonar esses princípios para utilizar Minimal APIs.
Na verdade, a escolha entre Minimal APIs e Controllers pode ser tratada como uma decisão da camada de apresentação ou de entrada HTTP.
Imagine uma aplicação estruturada com as seguintes camadas:
API: recebe requisições HTTP e produz respostas.
Application: coordena os casos de uso da aplicação.
Domain: contém as regras e os conceitos centrais do negócio.
Infrastructure: implementa integrações externas, persistência e outros detalhes técnicos.
Nesse cenário, tanto Minimal APIs quanto Controllers podem atuar como a camada de entrada.
O fluxo de uma requisição pode ser representado da seguinte maneira:
Cliente HTTP → Endpoint ou Controller → Caso de uso → Domínio e infraestrutura → Resposta HTTP.
O ponto fundamental é evitar que as regras de negócio dependam diretamente do mecanismo utilizado para expor os endpoints.
Por exemplo, considere um caso de uso responsável por criar um pedido.
A operação pode validar os produtos, calcular valores, verificar condições comerciais e coordenar a persistência dos dados.
Essas responsabilidades não precisam ficar dentro de um método MapPost nem dentro de uma ação de Controller.
O endpoint ou Controller deve receber a requisição, validar aspectos próprios do contrato HTTP, chamar o caso de uso e traduzir o resultado para uma resposta apropriada.
Essa organização permite trocar a camada de entrada sem precisar reescrever toda a lógica de negócio.
Uma possibilidade é criar um módulo para cada conjunto de endpoints.
Por exemplo:
src/
├── BackstageTech.Api/
│ ├── Endpoints/
│ │ ├── ProductEndpoints.cs
│ │ ├── CustomerEndpoints.cs
│ │ └── OrderEndpoints.cs
│ └── Program.cs
│
├── BackstageTech.Application/
│ ├── Products/
│ ├── Customers/
│ └── Orders/
│
├── BackstageTech.Domain/
│
└── BackstageTech.Infrastructure/
Essa estrutura é apenas uma sugestão. A organização exata deve refletir as responsabilidades e os padrões definidos para o projeto.
O importante é que os módulos HTTP não se transformem em locais para concentrar regras de negócio.
Uma Minimal API bem estruturada pode ser tão modular quanto uma aplicação baseada em Controllers.
Da mesma forma, utilizar Controllers não garante automaticamente uma arquitetura limpa. Se as classes de apresentação executarem consultas, implementarem regras comerciais e controlarem diretamente todos os detalhes de infraestrutura, a separação de responsabilidades continuará comprometida.
Sim. O ASP.NET Core permite mapear endpoints Minimal API e Controllers na mesma aplicação.
Isso pode ser útil durante uma migração gradual ou quando diferentes partes do sistema possuem requisitos distintos.
Por exemplo, uma aplicação existente pode manter os Controllers responsáveis por funcionalidades consolidadas e utilizar Minimal APIs para um novo conjunto de endpoints.
A configuração pode ser semelhante a esta:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.MapGet("/api/health", () =>
{
return Results.Ok(new
{
Status = "Healthy"
});
});
app.Run();
Nesse exemplo, a aplicação registra os Controllers e também define um endpoint Minimal API para verificar o estado do serviço.
A rota de saúde é apenas ilustrativa. Em produção, um endpoint desse tipo deve refletir uma estratégia de health checks adequada às necessidades da aplicação.
A utilização conjunta das duas abordagens pode facilitar a evolução de sistemas existentes sem exigir uma migração completa.
Entretanto, é importante estabelecer convenções claras para evitar duplicação de rotas, divergências no tratamento de erros e diferentes padrões de autorização para funcionalidades equivalentes.
Misturar as abordagens pode ser útil, mas deve resultar de uma decisão arquitetural consciente.
Na maioria dos casos, não vale a pena migrar uma API apenas para adotar uma abordagem mais recente.
Se o sistema funciona bem, possui testes confiáveis e atende aos requisitos de desempenho e manutenção, a migração pode representar um custo sem retorno proporcional.
Antes de tomar uma decisão, avalie os seguintes pontos:
Considere o volume de endpoints, os filtros existentes, os mecanismos de validação e os componentes que dependem do pipeline MVC.
Quanto maior a dependência de recursos específicos dos Controllers, maior poderá ser o esforço de adaptação.
Identifique o que a migração pretende melhorar.
O objetivo pode ser simplificar a estrutura, padronizar novos módulos ou aproveitar recursos disponíveis em uma versão recente do ASP.NET Core.
Entretanto, se a única justificativa for uma expectativa genérica de performance, realize testes antes de assumir que a mudança produzirá resultados relevantes.
Verifique se as bibliotecas internas e externas utilizadas pela aplicação oferecem suporte adequado à abordagem escolhida.
Também considere a versão do .NET, os requisitos de implantação e os padrões utilizados por outras equipes que dependem da API.
Se houver benefícios claros, considere começar por uma funcionalidade pequena e isolada.
Implemente os novos endpoints, preserve os contratos existentes e compare o comportamento com a versão anterior.
Essa estratégia permite avaliar os resultados antes de ampliar o escopo da mudança.
A migração deve ser orientada por necessidades concretas, e não pela ideia de que uma abordagem é necessariamente melhor em todos os aspectos.
A documentação oficial do ASP.NET Core apresenta as Minimal APIs como a abordagem recomendada para novos projetos de APIs HTTP, destacando sua simplicidade e seu foco em desempenho. Os Controllers continuam disponíveis como alternativa, especialmente para aplicações que precisam de recursos específicos do MVC ou que seguem esse modelo de organização.
Essa recomendação é um bom ponto de partida, mas não elimina a necessidade de analisar os requisitos do projeto.
Uma API pequena pode ser implementada de maneira direta com Minimal APIs. Uma aplicação empresarial que depende de recursos específicos do MVC pode continuar se beneficiando dos Controllers.
O melhor caminho é avaliar as necessidades técnicas e operacionais do sistema, considerando também a experiência da equipe e o custo de manutenção.
Para consultar os recursos disponíveis na versão atual do framework, recomendamos a documentação oficial:
Visão geral das APIs no ASP.NET Core: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/overview?view=aspnetcore-10.0
Criação de APIs Web com Controllers: https://learn.microsoft.com/pt-br/aspnet/core/web-api/?view=aspnetcore-10.0
Referência rápida das Minimal APIs: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis?view=aspnetcore-10.0
A escolha entre Minimal APIs e Controllers no ASP.NET Core depende principalmente da estrutura da aplicação, dos recursos necessários e das convenções adotadas pela equipe.
As Minimal APIs são uma excelente opção para novos projetos que procuram uma forma direta de construir endpoints HTTP, com menos código estrutural e flexibilidade para organizar funcionalidades em módulos.
Os Controllers continuam sendo uma alternativa sólida para sistemas que dependem de recursos específicos do MVC, seguem convenções consolidadas ou possuem uma arquitetura que já funciona bem com esse modelo.
Em termos práticos, podemos resumir a decisão da seguinte forma:
Escolha Minimal APIs quando quiser construir uma nova API HTTP com uma estrutura enxuta e não depender de recursos específicos do MVC.
Escolha Controllers quando os recursos do pipeline MVC, as convenções existentes ou as necessidades da equipe tornarem essa abordagem mais adequada.
Considere utilizar ambas quando houver uma necessidade concreta de evolução gradual ou quando diferentes módulos possuírem requisitos distintos.
Não migre um sistema funcional apenas por acreditar que Minimal APIs serão automaticamente mais rápidas ou mais fáceis de manter.
Minha recomendação é começar avaliando as Minimal APIs em novos projetos ASP.NET Core e manter os Controllers sempre que oferecerem vantagens concretas para o contexto da aplicação.
Mais importante do que escolher uma abordagem é manter uma boa separação de responsabilidades, implementar testes automatizados e garantir que a lógica de negócio não fique acoplada desnecessariamente à camada HTTP.
Uma API bem projetada pode ser construída com qualquer uma das duas alternativas.
E você, já utiliza Minimal APIs em projetos .NET ou continua preferindo Controllers? Qual abordagem considera mais adequada para aplicações empresariais? Compartilhe sua experiência nos comentários.