Escritura de middleware de ASP.NET Core personalizado
Por Rick Anderson y Steve Smith
El software intermedio es un software que se ensambla en una canalización de una aplicación para controlar las solicitudes y las respuestas. ASP.NET Core proporciona un completo conjunto de componentes de middleware integrados, pero en algunos escenarios es posible que quiera escribir middleware personalizado.
Nota
En este tema se describe cómo escribir middleware basado en convenciones. Para ver un enfoque que emplea el establecimiento de tipos seguros y la activación por solicitud, consulte Activación de middleware basada en Factory en ASP.NET Core.
Clase de middleware
El middleware normalmente está encapsulado en una clase y se expone con un método de extensión. Use el siguiente software intermedio a modo de ejemplo. En este se establece la referencia cultural de la solicitud actual a partir de la cadena de solicitud:
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
var cultureQuery = context.Request.Query["culture"];
if (!string.IsNullOrWhiteSpace(cultureQuery))
{
var culture = new CultureInfo(cultureQuery);
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture;
}
// Call the next delegate/middleware in the pipeline
await next();
});
app.Run(async (context) =>
{
await context.Response.WriteAsync(
$"Hello {CultureInfo.CurrentCulture.DisplayName}");
});
}
}
El código de ejemplo anterior se usa para mostrar la creación de un componente de software intermedio. Para obtener más información sobre la compatibilidad con la localización integrada de ASP.NET Core, vea Globalización y localización en ASP.NET Core.
Pruebe el middleware pasando la referencia cultural. Por ejemplo, solicite https://localhost:5001/?culture=no.
El código siguiente mueve el delegado de middleware a una clase:
using Microsoft.AspNetCore.Http;
using System.Globalization;
using System.Threading.Tasks;
namespace Culture
{
public class RequestCultureMiddleware
{
private readonly RequestDelegate _next;
public RequestCultureMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
var cultureQuery = context.Request.Query["culture"];
if (!string.IsNullOrWhiteSpace(cultureQuery))
{
var culture = new CultureInfo(cultureQuery);
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture;
}
// Call the next delegate/middleware in the pipeline
await _next(context);
}
}
}
La clase de middleware debe incluir:
- Un constructor público con un parámetro de tipo RequestDelegate.
- Un método público llamado
InvokeoInvokeAsync. Este método debe:- Devolver
Task. - Aceptar un primer parámetro de tipo HttpContext.
- Devolver
Los parámetros adicionales para el constructor y Invoke/InvokeAsync se rellenan mediante la inserción de dependencias (DI).
Dependencias de middleware
El middleware debería seguir el principio de dependencias explicitas mediante la exposición de sus dependencias en el constructor. El middleware se construye una vez por duración de la aplicación. Si necesita compartir servicios con software intermedio en una solicitud, vea la sección Dependencias de middleware bajo solicitud.
Los componentes de software intermedio pueden resolver sus dependencias de una inserción de dependencias (DI) mediante parámetros del constructor. UseMiddleware<T> también puede aceptar parámetros adicionales directamente.
Dependencias de middleware bajo solicitud
Dado que el software intermedio se construye al inicio de la aplicación y no bajo solicitud, los servicios de duración con ámbito que usan los constructores de software intermedio no se comparten con otros tipos insertados mediante dependencias durante cada solicitud. Si debe compartir un servicio con ámbito entre su middleware y otros tipos, agregue esos servicios a la signatura del método Invoke. El método Invoke puede aceptar parámetros adicionales que la inserción de dependencias propaga:
public class CustomMiddleware
{
private readonly RequestDelegate _next;
public CustomMiddleware(RequestDelegate next)
{
_next = next;
}
// IMyScopedService is injected into Invoke
public async Task Invoke(HttpContext httpContext, IMyScopedService svc)
{
svc.MyProperty = 1000;
await _next(httpContext);
}
}
Las opciones de registro y duración contienen un ejemplo completo de middleware con servicios de duración con ámbito.
Método de extensión de middleware
El método de extensión siguiente expone el software intermedio mediante IApplicationBuilder:
using Microsoft.AspNetCore.Builder;
namespace Culture
{
public static class RequestCultureMiddlewareExtensions
{
public static IApplicationBuilder UseRequestCulture(
this IApplicationBuilder builder)
{
return builder.UseMiddleware<RequestCultureMiddleware>();
}
}
}
El código siguiente llama al middleware desde Startup.Configure:
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.UseRequestCulture();
app.Run(async (context) =>
{
await context.Response.WriteAsync(
$"Hello {CultureInfo.CurrentCulture.DisplayName}");
});
}
}
Recursos adicionales
- Las opciones de registro y duración contienen un ejemplo completo de middleware con servicios de duración con ámbito, transitorios y singleton.
- Middleware de ASP.NET Core
- Prueba del middleware de ASP.NET Core
- Migración de controladores y módulos HTTP ASP.NET Core middleware
- Inicio de la aplicación en ASP.NET Core
- Características de solicitud de ASP.NET Core
- Activación de middleware basada en Factory en ASP.NET Core
- Activación de middleware con un contenedor de terceros en ASP.NET Core