No primeiro artigo da série, demos os primeiros passos com .NET, entendendo os fundamentos da plataforma, a estrutura de projetos e a execução de aplicações simples. A partir daqui, começamos a entrar em um território muito mais próximo da realidade profissional: a criação de APIs.
APIs estão presentes em praticamente todos os sistemas modernos. Elas conectam aplicações web, mobile, sistemas internos, microsserviços e soluções em nuvem. Entender como criar uma API bem estruturada com .NET é um passo essencial para quem quer evoluir como desenvolvedor.
Neste artigo, vamos construir uma API do zero, passo a passo, explicando não apenas como fazer, mas também porquê cada decisão é tomada. O objetivo é que, ao final, você tenha uma API funcional, compreenda sua estrutura e esteja preparado para evoluí-la nos próximos artigos da série.
Criar uma API em .NET hoje significa trabalhar com o ASP.NET Core, um framework moderno, performático e multiplataforma, amplamente utilizado em aplicações de produção. Quando você cria uma API com ASP.NET Core, o que está sendo executado por baixo dos panos é um servidor HTTP. Esse servidor fica responsável por:
- Escutar requisições HTTP (GET, POST, PUT, DELETE, etc.)
- Interpretar URLs e rotas
- Encaminhar a requisição para o endpoint correto
- Gerar e devolver uma resposta HTTP ao cliente
Em outras palavras, o ASP.NET Core atua como uma ponte entre o mundo HTTP e o seu código C#, fornecendo tudo o que precisamos para lidar com requisições, respostas, validar dados e integrar a aplicação com outros serviços e infraestruturas.
Antes de começar, é importante reforçar um ponto: embora existam diferentes abordagens para criar APIs (Controllers tradicionais, Minimal APIs, GraphQL), neste artigo vamos utilizar o modelo Web API com Controllers, pois ele ajuda a entender melhor conceitos fundamentais que serão reutilizados ao longo da carreira.
OBS: temos que esclarecer um ponto fundamental relacionado às versões mais recentes do .NET e ao template utilizado para criação de APIs. A partir do .NET 7, o template padrão criado pelo comando dotnet new webapi passou a utilizar Minimal APIs por padrão. Isso significa que, ao criar um novo projeto, não será gerada automaticamente a pasta Controllers nem um controller de exemplo, como acontecia em versões anteriores.
Neste artigo, vamos trabalhar com controllers tradicionais, mesmo utilizando o template moderno do .NET 9, pois eles ajudam a entender melhor conceitos como rotas, verbos HTTP, organização do código e estrutura de projetos, especialmente para quem está aprendendo.
Por isso, ao longo do passo a passo, iremos criar manualmente a pasta Controllers, os controllers de exemplo e ajustar o Program.cs para que a aplicação reconheça eles. Esse fluxo é totalmente válido, amplamente utilizado em projetos reais e faz parte do aprendizado.
Com isso esclarecido, certifique-se de que você já possui:
- .NET SDK instalado
- Um editor de código (Visual Studio ou VS Code)
- Conhecimento básico de C# e do primeiro artigo da série
Com isso em mãos, abra o terminal na pasta onde você costuma criar seus projetos. O primeiro passo é criar um novo projeto de API:
dotnet new webapi -n MinhaPrimeiraApiEsse comando cria um projeto de API completo, com diversas configurações iniciais prontas. Ao abrir o projeto no Visual Studio ou VS Code, você perceberá que a estrutura é um pouco maior do que a aplicação de console do artigo anterior. Isso acontece porque o template já inclui configurações para servidor HTTP, middlewares, logging e documentação.

Dentro do projeto, alguns arquivos merecem atenção especial desde o início.
Neste momento, você perceberá que não existe uma pasta chamada Controllers. Isso é esperado e faz parte do comportamento atual do template baseado em Minimal APIs. Vamos criar essa pasta manualmente nos próximos passos.
Outro arquivo que merece atenção é o Program.cs, que agora tem mais responsabilidades. Mesmo que, neste momento, ele pareça complexo, é importante entender que:
- Ele configura o servidor HTTP
- Registra dependências dos serviços
- Define o pipeline de middlewares
- Mapeia os endpoints
Não se preocupe em dominar tudo agora. Ao longo da série, esse arquivo ficará cada vez mais claro conforme novos conceitos forem introduzidos.
Como o template não cria controllers automaticamente, o próximo passo é criar manualmente a pasta que será responsável por concentrar as classes que expõem os endpoints da API. Crie uma pasta chamada Controllers na raiz do projeto e, dentro dela, crie um arquivo chamado ExemploController.cs.


O arquivo criado estará inicialmente vazio, mas podemos adicionar um exemplo simples de controller, que funcione perfeitamente.

using Microsoft.AspNetCore.Mvc;
namespace MinhaPrimeiraApi.Controllers
{
[ApiController]
[Route("[controller]")]
public class ExemploController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return Ok("Minha primeira API está funcionando!");
}
}
}Código disponível para copiar
Esse pequeno código já introduz vários conceitos fundamentais, com um padrão de comunicação que é a base de praticamente todas as APIs REST:
- Controllers - é uma classe responsável por expor endpoints HTTP. Cada método público pode representar uma operação da API.
- Rotas - o atributo [Route("[controller]")] define o caminho da URL. Nesse caso, o nome do controller (ExemploController) vira automaticamente a rota /exemplo.
- Verbos HTTP - o atributo [HttpGet] indica que esse método responde a requisições HTTP do tipo GET, que são utilizadas para consulta de dados.
- Respostas HTTP - o método Ok() retorna uma resposta HTTP com status 200 (OK). Em APIs REST, o status code é tão importante quanto o conteúdo da resposta.
Agora vamos executar a aplicação. No terminal, dentro da pasta do projeto, rode:
dotnet runAo rodar o projeto, o .NET inicializa um servidor local. Normalmente, ele estará disponível em algo como:
https://localhost:5001OBS: lembre de alterar a porta (5001) conforme a que estiver no seu console. No meu caso, por exemplo, estou utilizando 7150.
Neste ponto, é comum acontecer algo que confunde quem está começando: ao acessar a rota do controller, a aplicação pode retornar erro 404. Isso não é um erro no controller e nem significa que o código está errado. Nas versões mais recentes do .NET, o template criado pelo comando dotnet new webapi é baseado em Minimal APIs. Isso significa que, por padrão, o projeto não vem configurado para usar controllers tradicionais, ele vem semelhante a isto:

Observe que:
- Não existe chamada para AddControllers()
- Não existe chamada para MapControllers()
- Os endpoints são definidos diretamente no Program.cs usando MapGet, MapPost, etc.
Mesmo que você crie um controller manualmente, o ASP.NET Core só irá reconhecê-lo se ele estiver devidamente registrado no pipeline da aplicação. Para que controllers tradicionais funcionem, duas configurações são obrigatórias:
- Registrar controllers no container de serviços
- Mapear controllers no pipeline HTTP
Como neste artigo estamos utilizando controllers tradicionais para fins didáticos, precisamos adaptar o Program.cs para que ele suporte esse modelo. Após as alterações, o arquivo deve estar assim:

OBS: Os endpoints definidos via Minimal APIs, como o MapGet("/weatherforecast"), podem ser removidos ou mantidos, mas para fins didáticos, neste artigo focaremos apenas nos controllers.
var builder = WebApplication.CreateBuilder(args);
// Add services to the container (traditional controllers).
builder.Services.AddControllers();
// Add OpenAPI (Swagger).
builder.Services.AddOpenApi();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
app.UseHttpsRedirection();
// Map Controllers.
app.MapControllers();
app.Run();Código disponível para copiar
Com tudo ajustado, se você rodar o projeto novamente e acessar no navegador:
https://localhost:5001/exemploDeverá ver a mensagem retornada pelo controller, confirmando que sua API está funcionando corretamente.

Isso confirma que a aplicação está corretamente configurada para utilizar controllers tradicionais, mesmo partindo do template moderno do .NET 9.
Com a API funcionando, vamos evoluir para um cenário mais realista. Em vez de retornar uma string fixa, vamos trabalhar com dados. Na raiz do projeto, crie uma pasta chamada Models e, dentro dela, o arquivo Produto.cs, nele vamos adicionar uma classe simples:

namespace MinhaPrimeiraApi.Models
{
public class Produto
{
public int Id { get; set; }
public string Nome { get; set; }
public decimal Preco { get; set; }
}
}Código disponível para copiar
Essa classe representa um recurso da nossa API. Em APIs REST, tudo gira em torno de recursos, que são as representações das entidades do sistema.
Agora vamos criar um novo controller chamado ProdutosController.cs:

using Microsoft.AspNetCore.Mvc;
using MinhaPrimeiraApi.Models;
namespace MinhaPrimeiraApi.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class ProdutosController : ControllerBase
{
private static readonly List<Produto> Produtos = new()
{
new Produto { Id = 1, Nome = "Teclado", Preco = 150 },
new Produto { Id = 2, Nome = "Mouse", Preco = 80 }
};
[HttpGet]
public IActionResult Get()
{
return Ok(Produtos);
}
}
}Código disponível para copiar
Aqui estamos utilizando uma lista em memória apenas para fins didáticos. Em projetos reais, esses dados normalmente vêm de um banco de dados.
Agora, ao rodar o projeto novamente e acessar:
https://localhost:5001/api/produtosEsse endpoint:
- Responde a requisições GET
- Retorna uma coleção de produtos
- Produz uma resposta HTTP 200, que nesse caso será um JSON com a lista de produtos

Agora, na ProdutosController.cs, vamos adicionar um endpoint para criar novos produtos:

[HttpPost]
public IActionResult Post(Produto produto)
{
Produtos.Add(produto);
return CreatedAtAction(nameof(Get), produto);
}Esse método responde a requisições POST e recebe um objeto Produto no corpo da requisição. Para testar esse endpoint, você pode usar ferramentas como Postman, Insomnia ou até extensões do VS Code, usando um JSON como:
{
"id": 3,
"nome": "Monitor",
"preco": 1200
}Quando o cliente envia um JSON desse tipo, o ASP.NET Core:
- Lê o corpo da requisição HTTP
- Converte o JSON para um objeto Produto
- Injeta esse objeto diretamente no parâmetro do método
Tudo isso acontece automaticamente, sem código adicional, por conta do processo de model binding. Esse é um dos pontos mais poderosos do framework.
Com esses dois endpoints, já temos uma API funcional com operações básicas. Mesmo sendo simples, ela já segue padrões usados em sistemas reais. Neste ponto, vale uma observação importante: no início da carreira, é comum focar apenas em fazer a API funcionar. Porém, com o tempo, você perceberá a importância de:
- Validação de dados
- Tratamento de erros
- Padronização de respostas
- Separação de responsabilidades
Esses temas serão explorados nos próximos artigos.
Antes de encerrar, é importante reforçar que essa API é apenas um ponto de partida. Em produção, dificilmente você trabalhará com listas em memória. Entram em cena conceitos como:
- Injeção de dependência
- Entity Framework Core
- Banco de dados
- Versionamento de API
- Autenticação e autorização
Tudo isso se apoia diretamente nos fundamentos que você acabou de praticar.
Criar sua primeira API com .NET é um marco importante na jornada de qualquer desenvolvedor. A partir daqui, o código deixa de ser apenas exercício e começa a se parecer com soluções reais. No próximo artigo da série, vamos evoluir essa API, introduzindo boas práticas de organização, separação em camadas e integração com banco de dados, aproximando ainda mais o projeto de um cenário profissional.
A ideia é continuar avançando passo a passo, sempre conectando teoria com prática, para que cada novo conceito faça sentido dentro de um projeto real.
Disponibilizei o projeto de exemplo que usamos aqui no artigo. Você pode baixar direto do GitHub clicando aqui!