Visão geral do pipeline do ASP.NET Core
Entenda como as requisições percorrem o pipeline de middleware e o HttpContext e como as respostas são construídas.
Visão geral do pipeline do ASP.NET Core é uma aula grátis de C# Academy no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de C# Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de C# Academy inclui 4 aulas no total.
O fluxo de processamento de requisições
Toda requisição HTTP no ASP.NET Core passa por um fluxo de processamento de componentes intermediários. Cada componente pode inspecionar, modificar, interromper antecipadamente ou encaminhar a requisição para o componente seguinte. Entender esse fluxo é fundamental para criar aplicações ASP.NET Core.
HttpContext: o envelope da requisição
HttpContext transporta tudo sobre uma requisição e uma resposta: cabeçalhos, cookies, corpo, declarações do usuário, informações da conexão e o token de cancelamento. Todos os componentes intermediários operam sobre ele.
app.Use(async (context, next) =>
{
// Read request info
var method = context.Request.Method;
var path = context.Request.Path;
var headers = context.Request.Headers;
var user = context.User.Identity?.Name;
// Write to response
context.Response.Headers.Append("X-Processed-By", "MyMiddleware");
await next(context); // forward to next middleware
});Ordem de registro dos componentes intermediários
Os componentes intermediários são executados na ordem em que são registrados. A resposta é desembrulhada na ordem inversa, como uma pilha. A ordem é crítica: a autenticação deve ser executada antes da autorização; o roteamento, antes da correspondência com pontos de extremidade.
// Typical order for an ASP.NET Core app:
app.UseExceptionHandler("/error"); // outermost — catches everything
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors("policy");
app.UseAuthentication(); // must be before Authorization
app.UseAuthorization();
app.UseRateLimiter();
app.UseOutputCache();
// MapHub, MapControllers, MapGet etc.
app.Run();Use, Run e Map
Três métodos adicionam componentes intermediários: Use, que chama o próximo; Run, que é terminal e NUNCA chama o próximo; e Map, que cria ramificações com base no caminho.
// Use: passes to next
app.Use(async (ctx, next) =>
{
Console.WriteLine("Before");
await next(ctx);
Console.WriteLine("After");
});
// Run: terminal — no next
app.Run(async ctx =>
await ctx.Response.WriteAsync("Terminal"));
// Map: branch on path prefix
app.Map("/api", apiApp =>
apiApp.Run(async ctx =>
await ctx.Response.WriteAsync("API branch")));Corpos de requisição e resposta
Os corpos da requisição e da resposta são fluxos. A leitura do corpo da requisição só pode ser feita uma vez — habilite o armazenamento em buffer do corpo da requisição se precisar lê-lo várias vezes, por exemplo, em vários componentes intermediários.
app.Use(async (ctx, next) =>
{
// Enable buffering so body can be read multiple times
ctx.Request.EnableBuffering();
using var reader = new StreamReader(
ctx.Request.Body,
leaveOpen: true);
var body = await reader.ReadToEndAsync();
ctx.Request.Body.Position = 0; // rewind for next middleware
Console.WriteLine($"Body: {body}");
await next(ctx);
});Interrupção antecipada do fluxo de processamento
Um componente intermediário pode interromper antecipadamente o fluxo escrevendo a resposta e NÃO chamando next. Isso é útil para bloqueios de autenticação, verificações de integridade ou páginas de manutenção.
app.Use(async (ctx, next) =>
{
if (ctx.Request.Path == "/maintenance")
{
ctx.Response.StatusCode = 503;
await ctx.Response.WriteAsync("Service under maintenance");
return; // short-circuit — next is NOT called
}
await next(ctx);
});A interface IMiddleware
Para um componente intermediário baseado em classe que precise de DI, implemente IMiddleware. Registre a implementação no DI e use app.UseMiddleware<T>().
public class RequestTimingMiddleware : IMiddleware
{
private readonly ILogger<RequestTimingMiddleware> _logger;
public RequestTimingMiddleware(ILogger<RequestTimingMiddleware> l) => _logger = l;
public async Task InvokeAsync(HttpContext ctx, RequestDelegate next)
{
var sw = System.Diagnostics.Stopwatch.StartNew();
await next(ctx);
_logger.LogInformation("{Method} {Path}: {Ms}ms",
ctx.Request.Method, ctx.Request.Path, sw.ElapsedMilliseconds);
}
}
// Register:
builder.Services.AddTransient<RequestTimingMiddleware>();
app.UseMiddleware<RequestTimingMiddleware>();Classes convencionais de componentes intermediários
Como alternativa, crie uma classe com um método InvokeAsync(HttpContext, RequestDelegate). A estrutura injeta as dependências, incluindo o delegado seguinte, por meio do construtor.
public class ApiKeyMiddleware
{
private readonly RequestDelegate _next;
private readonly string _key;
// RequestDelegate injected by framework
public ApiKeyMiddleware(RequestDelegate next, IConfiguration cfg)
{
_next = next;
_key = cfg["ApiKey"] ?? "";
}
public async Task InvokeAsync(HttpContext ctx)
{
if (ctx.Request.Headers["X-Api-Key"] != _key)
{
ctx.Response.StatusCode = 401;
return;
}
await _next(ctx);
}
}Modificação de respostas depois do próximo componente
O código depois de await next(ctx) é executado depois que a resposta começa a ser escrita. Você pode adicionar cabeçalhos à resposta antes de next, mas não pode modificar o código de status nem o corpo depois disso.
app.Use(async (ctx, next) =>
{
// Before: add response headers (safe)
ctx.Response.OnStarting(() =>
{
ctx.Response.Headers.Append("X-Request-Id",
Guid.NewGuid().ToString("N"));
return Task.CompletedTask;
});
await next(ctx);
// After: response may already be sent
// SAFE: logging, metrics
// UNSAFE: changing status code or writing body
Console.WriteLine($"Response status: {ctx.Response.StatusCode}");
});Na prática: componente intermediário de ID de correlação
Um componente intermediário de ID de correlação de produção que adiciona um ID de rastreamento a cada requisição para rastreamento distribuído e registro.
public class CorrelationIdMiddleware
{
private readonly RequestDelegate _next;
private const string Header = "X-Correlation-Id";
public CorrelationIdMiddleware(RequestDelegate next) => _next = next;
public async Task InvokeAsync(HttpContext ctx)
{
var correlationId = ctx.Request.Headers[Header].FirstOrDefault()
?? Guid.NewGuid().ToString("N");
ctx.Items["CorrelationId"] = correlationId;
ctx.Response.OnStarting(() =>
{
ctx.Response.Headers.Append(Header, correlationId);
return Task.CompletedTask;
});
using (Serilog.Context.LogContext.PushProperty("CorrelationId", correlationId))
await _next(ctx);
}
}Verificação rápida
Qual é a diferença entre app.Use() e app.Run() ao adicionar um componente intermediário?
Recapitulação: visão geral do fluxo de processamento do ASP.NET Core
Principais conclusões:
- Os componentes intermediários são executados na ordem de registro; as respostas são desembrulhadas na ordem inversa
- Use → chama o próximo; Run → terminal; Map → ramificação baseada no caminho
- HttpContext contém a requisição, a resposta, o usuário e o token de cancelamento
- Habilite o armazenamento em buffer para ler o corpo da requisição várias vezes
- A interface IMiddleware permite componentes intermediários baseados em classes e compatíveis com DI
- Adicione cabeçalhos à resposta via OnStarting(); não altere o status depois do próximo componente
Perguntas Frequentes
A aula “Visão geral do pipeline do ASP.NET Core” é grátis?
Sim — o texto completo de “Visão geral do pipeline do ASP.NET Core” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de C# Academy, atualize para CoddyKit PRO. O curso de C# Academy inclui 4 aulas no total.
O que vou aprender em “Visão geral do pipeline do ASP.NET Core”?
Entenda como as requisições percorrem o pipeline de middleware e o HttpContext e como as respostas são construídas. Você pratica C# Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar C# Academy?
Nenhuma experiência prévia é necessária. C# Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.
Quanto tempo leva a aula “Visão geral do pipeline do ASP.NET Core”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de C# Academy?
Sim. Cada aula de C# Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Visão geral do pipeline do ASP.NET Core
- Escrevendo middleware personalizado
- Interrupção antecipada e ramificação
- Ordenação do middleware e middleware integrado