0Pricing
C# Academy · Aula

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

  1. Visão geral do pipeline do ASP.NET Core
  2. Escrevendo middleware personalizado
  3. Interrupção antecipada e ramificação
  4. Ordenação do middleware e middleware integrado
← Voltar para C# Academy