Descripción general de la canalización de ASP.NET Core
Comprenda cómo fluyen las solicitudes por la canalización de middleware y HttpContext, y cómo se construyen las respuestas.
Descripción general de la canalización de ASP.NET Core es una lección gratuita de C# Academy en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de C# Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de C# Academy incluye 4 lecciones en total.
El pipeline de solicitudes
Cada solicitud HTTP en ASP.NET Core fluye a través de un pipeline de middleware. Cada componente de middleware puede inspeccionar, modificar, interrumpir o reenviar la solicitud al componente siguiente. Comprender este pipeline es fundamental para crear aplicaciones de ASP.NET Core.
HttpContext: el contenedor de la solicitud
HttpContext contiene toda la información de una solicitud y su respuesta: encabezados, cookies, cuerpo, notificaciones del usuario, información de la conexión y el token de cancelación. Todo el middleware opera sobre él.
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
});Orden de registro del middleware
El middleware se ejecuta en el orden en que se registra. La respuesta se deshace en orden inverso, como una pila. El orden es fundamental: la autenticación debe ejecutarse antes que la autorización, y el enrutamiento antes de la coincidencia con los endpoints.
// 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 y Map
Tres métodos agregan middleware: Use (llama al siguiente), Run (terminal, nunca llama al siguiente) y Map (crea una bifurcación según la ruta).
// 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")));Cuerpos de las solicitudes y respuestas
Los cuerpos de las solicitudes y las respuestas son streams. La lectura del cuerpo de una solicitud solo puede hacerse una vez; habilite el almacenamiento en búfer del cuerpo si necesita leerlo varias veces, por ejemplo, en varios componentes de middleware.
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);
});Interrupción del pipeline
El middleware puede interrumpir el pipeline escribiendo la respuesta y NO llamando a next. Esto resulta útil para controles de autenticación, comprobaciones de estado o páginas de mantenimiento.
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);
});La interfaz IMiddleware
Para crear middleware basado en clases que necesite DI, implemente IMiddleware. Registre la implementación en DI y 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>();Clases de middleware convencionales
Como alternativa, cree una clase con un método InvokeAsync(HttpContext, RequestDelegate). El framework inyecta las dependencias, incluido el delegado siguiente, mediante el constructor.
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);
}
}Modificación de respuestas después de next
El código que aparece después de await next(ctx) se ejecuta cuando la respuesta ya ha empezado a escribirse. Puede agregar encabezados de respuesta antes de next, pero no puede modificar el código de estado ni el cuerpo después de ese punto.
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}");
});Caso real: middleware de ID de correlación
Un middleware de ID de correlación de producción que agrega un ID de traza a cada solicitud para el seguimiento distribuido y el 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);
}
}Comprobación rápida
¿Cuál es la diferencia entre app.Use() y app.Run() al agregar middleware?
Resumen: introducción al pipeline de ASP.NET Core
Conclusiones clave:
- El middleware se ejecuta en el orden de registro; las respuestas se deshacen en orden inverso
- Use → llama al siguiente; Run → terminal; Map → bifurcación basada en la ruta
- HttpContext contiene la solicitud, la respuesta, el usuario y el token de cancelación
- Habilite el almacenamiento en búfer para leer el cuerpo de la solicitud varias veces
- La interfaz IMiddleware permite crear middleware basado en clases compatible con DI
- Agregue encabezados de respuesta mediante OnStarting(); no cambie el estado después de next
Preguntas frecuentes
¿La lección «Descripción general de la canalización de ASP.NET Core» es gratis?
Sí — el texto completo de «Descripción general de la canalización de ASP.NET Core» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de C# Academy, actualiza a CoddyKit PRO. El curso de C# Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Descripción general de la canalización de ASP.NET Core»?
Comprenda cómo fluyen las solicitudes por la canalización de middleware y HttpContext, y cómo se construyen las respuestas. Practicas C# Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar C# Academy?
No se requiere experiencia previa. C# Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.
¿Cuánto tiempo toma la lección «Descripción general de la canalización de ASP.NET Core»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de C# Academy?
Sí. Cada lección de C# Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Descripción general de la canalización de ASP.NET Core
- Escritura de middleware personalizado
- Cortocircuito y ramificación
- Orden del middleware y middleware integrado