Claude Code + ASP.NET Core: scaffold, CRUD e testes xUnit
Veja como usar o Claude Code pra criar uma Web API ASP.NET Core, gerar migrations do EF Core e escrever testes xUnit sem sair do terminal.

Você provavelmente já usou o Claude ou o ChatGPT pra escrever um endpoint ASP.NET Core. Cola o model, pede o controller, copia a resposta, ajusta no IDE, percebe que falta a injeção de dependência, volta pro chat, manda mais contexto, copia de novo. Funciona. Mas você ainda é o elo de integração entre o chat e o código.
Claude Code elimina esse vai e vem. Você abre o terminal na raiz do projeto, descreve o que quer, e o agente edita os arquivos, roda os comandos e lê os erros. Sem trocar de janela.
O tutorial cobre um projeto real com .NET 10: Web API, Entity Framework Core com PostgreSQL, migrations e testes xUnit. Do scaffold ao teste passando, tudo pelo terminal.
O que você precisa
- .NET 10 SDK instalado (
dotnet --versionretornando10.x) - Node.js 18+ para instalar o Claude Code via npm
- Claude Code:
npm install -g @anthropic-ai/claude-code - Conta Anthropic com Claude Pro (US$20/mês) ou créditos de API
Se você nunca rodou o claude no terminal, leia o que é Claude Code e como instalar antes de continuar. Esse tutorial assume que você já passou pela tela inicial e sabe confirmar as ações do agente.
Passo 1: scaffold do projeto
Crie uma pasta vazia e abra o Claude Code:
mkdir produtos-api && cd produtos-api
claude
Na sessão que abre, escreva sua primeira instrução em português mesmo:
cria um projeto Web API com .NET 10, Entity Framework Core e Npgsql (PostgreSQL).
Estrutura: pasta src/ProdutosApi com o projeto principal e src/ProdutosApi.Tests com xUnit.
Adiciona os pacotes NuGet necessários em cada projeto e cria o arquivo de solução.
O agente vai rodar dotnet new webapi, dotnet new xunit, dotnet add package pra cada dependência e dotnet sln add pra montar a solução. Você confirma cada comando antes de executar.
E aí em menos de dois minutos você tem uma solução .NET pronta com dois projetos referenciados, sem ter digitado um único dotnet new.

Passo 2: model e DbContext
Com a estrutura pronta, peça o model e o contexto:
cria um model Produto com:
- Id: int, chave primária gerada pelo banco
- Nome: string obrigatório, máximo 200 caracteres
- Preco: decimal obrigatório, positivo
- CriadoEm: DateTime UTC, preenchido automaticamente na criação
- DeletadoEm: DateTime? nullable, para soft delete
Cria o ProdutoContext com DbSet<Produto>.
Configura a string de conexão no appsettings.json e registra no Program.cs com AddDbContext.
O agente cria o model com DataAnnotations, o ProdutoContext, e o registro no Program.cs. O código vai sair assim:
// Models/Produto.cs
public class Produto
{
public int Id { get; set; }
[Required, MaxLength(200)]
public string Nome { get; set; } = string.Empty;
[Range(0.01, double.MaxValue)]
public decimal Preco { get; set; }
public DateTime CriadoEm { get; set; }
public DateTime? DeletadoEm { get; set; }
}
Você confere, ajusta se precisar, e segue.
Antes de ir pro controller, vale um investimento de dois minutos: se você configurar um CLAUDE.md no projeto com as convenções do seu time (naming, padrão de resposta da API, tratamento de erro), o agente vai seguir isso em todos os arquivos que criar daqui pra frente. Sem você repetir nas instruções.
Passo 3: endpoints CRUD com Minimal API
cria os endpoints de Produtos usando Minimal API (não controller class) com TypedResults:
- GET /produtos: lista paginada (page e pageSize como query params, padrão 1 e 20).
Filtra apenas onde DeletadoEm é null.
- GET /produtos/{id}: retorna 404 se não encontrar ou se estiver deletado.
- POST /produtos: valida o model, preenche CriadoEm com DateTime.UtcNow, retorna 201 Created.
- PUT /produtos/{id}: atualiza Nome e Preco, retorna 404 se não encontrar.
- DELETE /produtos/{id}: soft delete, preenche DeletadoEm com DateTime.UtcNow, retorna 204.
O agente cria o arquivo de endpoints, implementa a paginação com Skip e Take, trata erros com TypedResults.NotFound() e TypedResults.ValidationProblem(), e registra as rotas no Program.cs com app.MapGroup("/produtos").
Mas olha só o detalhe que importa: o Claude Code lembra do contexto da sessão inteira. Você pediu soft delete quando criou o model. Ele não vai esquecer disso no GET e retornar produtos deletados — o filtro já vem correto na primeira vez.
Isso é diferente de copiar código de um chat. O agente mantém coerência entre todos os arquivos porque leu o projeto inteiro antes de começar a editar.
Passo 4: migration do EF Core
Com model e DbContext configurados:
gera a migration inicial com o nome InitialCreate e aplica no banco.
A string de conexão no appsettings.Development.json já está configurada.
O agente roda:
dotnet ef migrations add InitialCreate --project src/ProdutosApi
dotnet ef database update --project src/ProdutosApi
Se o EF CLI não estiver instalado globalmente, ele instala antes com dotnet tool install --global dotnet-ef. Se der erro de conexão com o PostgreSQL, ele lê a mensagem de erro, explica o que está errado (host incorreto, credenciais, banco não criado) e pergunta como quer resolver.
Esse loop de leitura de erro e correção automática é onde o modelo de agente ganha do copilot de IDE. Não é só "executar o comando" — é interpretar o que voltou e decidir o próximo passo. A documentação de migrations do EF Core no Microsoft Learn tem todos os detalhes sobre gerenciamento de migrations em produção.
Passo 5: testes xUnit
cria testes xUnit no projeto ProdutosApi.Tests cobrindo:
1. GET /produtos retorna lista vazia quando não tem produtos cadastrados
2. GET /produtos retorna apenas produtos onde DeletadoEm é null
3. POST /produtos com dados válidos retorna 201 e o produto no corpo da resposta
4. POST /produtos com Nome vazio retorna 400
5. GET /produtos/{id} com id inexistente retorna 404
6. DELETE /produtos/{id} preenche DeletadoEm e o produto não aparece no GET
Usa EF Core InMemoryDatabase. Não precisa mockar o DbContext.
O agente cria a classe de testes com ProdutoContext configurado via UseInMemoryDatabase("TestDb") e implementa cada caso com [Fact] e assertions do xUnit. O caso de soft delete fica assim:
[Fact]
public async Task Get_NaoRetornaProdutosDeletados()
{
var produto = new Produto
{
Nome = "Teclado Mecânico",
Preco = 350m,
CriadoEm = DateTime.UtcNow
};
_context.Produtos.Add(produto);
await _context.SaveChangesAsync();
produto.DeletadoEm = DateTime.UtcNow;
await _context.SaveChangesAsync();
var response = await _app.GetAsync("/produtos");
var resultado = await response.Content.ReadFromJsonAsync<List<Produto>>();
Assert.Empty(resultado!);
}
Você vai querer revisar os testes antes de commitar. O agente às vezes gera setup ligeiramente verboso quando tem atalho mais direto. Mas como ponto de partida, você tem 6 casos com cobertura real em minutos.
Só que tem uma melhoria fácil de adicionar: configure um hook PostToolUse no Claude Code que roda dotnet test toda vez que o agente editar um .cs. Você passa a receber feedback imediato de regressão sem precisar lembrar de rodar o teste manualmente.
A documentação do xUnit para .NET mostra como configurar output detalhado e paralelismo de testes, que começa a importar quando a suíte cresce.

Quando o agente comete um erro
Vai acontecer. O Claude Code pode gerar código que compila mas tem comportamento errado. Esse é um dos motivos pra ter os testes: eles vão pegar isso antes de você.
Se o teste de soft delete falhar porque o GET está retornando produtos deletados, você descreve o problema na sessão:
o GET /produtos está retornando produtos onde DeletadoEm não é null.
O filtro Where está errado.
Ele abre o arquivo correto, localiza a query, corrige o Where, e a sessão segue. A vantagem de um agente com contexto completo é que ele já sabe em qual arquivo está o problema antes de você apontar.
Na prática, o loop fica: instrução → código gerado → rodar testes → descrever o que falhou → correção. Cada iteração é mais rápida que o ciclo de chat porque o agente nunca perde o fio do que foi pedido.
Próximo nível: MCP e multi-agents
O que vimos aqui é o fluxo base de um dev .NET com Claude Code. Com MCP servers configurados, o agente pode consultar o PostgreSQL em tempo real durante o desenvolvimento, verificar se os dados no banco batem com o que o código espera, e detectar inconsistências sem você sair do terminal.
Pra quem quer um caminho estruturado pelo fluxo completo, o curso de Claude Code para devs C#/.NET cobre sub-agents pra tarefas paralelas, Plan Mode pra features grandes, e os workflows de multi-agents que escrevem e testam ao mesmo tempo, com exemplos reais em ASP.NET Core.