Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Observação
Esta não é a versão mais recente deste artigo. Para a versão atual, consulte a versão .NET 10 deste artigo.
Advertência
Esta versão do ASP.NET Core não é mais suportada. Para obter mais informações, consulte a Política de suporte do .NET e do .NET Core. Para a versão atual, consulte a versão .NET 9 deste artigo.
Por Fiyaz Hasan, Rick Anderson e Steve Smith
Middleware é um software montado em um pipeline de aplicativos para lidar com solicitações e respostas. ASP.NET Core fornece um conjunto avançado de componentes de middleware integrados, mas em alguns cenários você pode querer escrever um middleware personalizado.
Este tópico descreve como escrever middleware baseado em convenção. Para obter uma abordagem que usa digitação forte e ativação por solicitação, consulte Ativação de middleware baseada em fábrica no ASP.NET Core.
Classe middleware
O middleware geralmente é encapsulado em uma classe e exposto com um método de extensão. Considere o seguinte middleware embutido, que define a cultura para a solicitação atual a partir de uma cadeia de caracteres de consulta:
using System.Globalization;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseHttpsRedirection();
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(context);
});
app.Run(async (context) =>
{
await context.Response.WriteAsync(
$"CurrentCulture.DisplayName: {CultureInfo.CurrentCulture.DisplayName}");
});
app.Run();
O middleware inline destacado anteriormente é usado para demonstrar a criação de um componente de middleware ao chamar Microsoft.AspNetCore.Builder.UseExtensions.Use. O método de extensão anterior Use adiciona um delegado de middleware definido diretamente ao pipeline de solicitação do aplicativo.
Há duas sobrecargas disponíveis para a Use extensão:
- Leva-se um HttpContext e um
Func<Task>. Invoque oFunc<Task>sem quaisquer parâmetros. - O outro leva um
HttpContexte um RequestDelegate. Invoque oRequestDelegatepassandoHttpContext.
Prefira usar a sobrecarga posterior, pois ela salva duas alocações internas por solicitação que são necessárias ao usar a outra sobrecarga.
Teste o middleware passando na cultura. Por exemplo, solicite https://localhost:5001/?culture=es-es.
Para obter o suporte interno à localização do ASP.NET Core, consulte Globalização e localização no ASP.NET Core.
O código a seguir move o delegado de middleware para uma classe:
using System.Globalization;
namespace Middleware.Example;
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);
}
}
A classe de middleware deve incluir:
- Um construtor público com um parâmetro do tipo RequestDelegate.
- Um método público chamado
InvokeouInvokeAsync. Este método deve:- Devolver um
Taskficheiro . - Aceite um primeiro parâmetro do tipo HttpContext.
- Devolver um
Parâmetros adicionais para o construtor e Invoke/InvokeAsync são preenchidos por injeção de dependência (DI).
Normalmente, um método de extensão é criado para expor o middleware através de IApplicationBuilder:
using System.Globalization;
namespace Middleware.Example;
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);
}
}
public static class RequestCultureMiddlewareExtensions
{
public static IApplicationBuilder UseRequestCulture(
this IApplicationBuilder builder)
{
return builder.UseMiddleware<RequestCultureMiddleware>();
}
}
O código a seguir chama o middleware de Program.cs:
using Middleware.Example;
using System.Globalization;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseHttpsRedirection();
app.UseRequestCulture();
app.Run(async (context) =>
{
await context.Response.WriteAsync(
$"CurrentCulture.DisplayName: {CultureInfo.CurrentCulture.DisplayName}");
});
app.Run();
Dependências de middleware
O middleware deve seguir o princípio de dependências explícitas expondo suas dependências em seu construtor. O middleware é construído uma vez por tempo de vida do aplicativo.
Os componentes de middleware podem resolver suas dependências a partir da injeção de dependência (DI) por meio de parâmetros do construtor. UseMiddleware também pode aceitar parâmetros adicionais diretamente.
Dependências de middleware por solicitação
O middleware é construído na inicialização do aplicativo e, portanto, tem tempo de vida útil do aplicativo.
Os serviços de ciclo de vida com escopo usados por construtores de middleware não são compartilhados com outros tipos injetados por dependência durante cada solicitação. Para compartilhar um serviço com escopo entre middleware e outros tipos, adicione esses serviços à assinatura do InvokeAsync método. O InvokeAsync método pode aceitar parâmetros adicionais que são preenchidos por DI:
namespace Middleware.Example;
public class MyCustomMiddleware
{
private readonly RequestDelegate _next;
public MyCustomMiddleware(RequestDelegate next)
{
_next = next;
}
// IMessageWriter is injected into InvokeAsync
public async Task InvokeAsync(HttpContext httpContext, IMessageWriter svc)
{
svc.Write(DateTime.Now.Ticks.ToString());
await _next(httpContext);
}
}
public static class MyCustomMiddlewareExtensions
{
public static IApplicationBuilder UseMyCustomMiddleware(
this IApplicationBuilder builder)
{
return builder.UseMiddleware<MyCustomMiddleware>();
}
}
As opções de ciclo de vida e registo contêm uma amostra completa de middleware com serviços com ciclo de vida delimitado.
O código a seguir é usado para testar o middleware anterior:
using Middleware.Example;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<IMessageWriter, LoggingMessageWriter>();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseMyCustomMiddleware();
app.MapGet("/", () => "Hello World!");
app.Run();
A interface IMessageWriter e a sua implementação
namespace Middleware.Example;
public interface IMessageWriter
{
void Write(string message);
}
public class LoggingMessageWriter : IMessageWriter
{
private readonly ILogger<LoggingMessageWriter> _logger;
public LoggingMessageWriter(ILogger<LoggingMessageWriter> logger) =>
_logger = logger;
public void Write(string message) =>
_logger.LogInformation(message);
}
Recursos adicionais
- Código de exemplo usado neste artigo
- Fonte UseExtensions no GitHub
- Opções de tempos de vida e registo contém uma amostra completa de middleware com serviços de ciclo de vida: com escopo, transitórioe singleton.
- ANÁLISE APROFUNDADA: COMO É CONSTRUÍDO O PIPELINE DE MIDDLEWARE DO ASP.NET CORE
- Middleware do ASP.NET Core
- Teste o middleware Core do ASP.NET
- Migrar módulos HTTP para middleware ASP.NET Core
- Inicialização do aplicativo no ASP.NET Core
- Solicitar Funcionalidades no ASP.NET Core
- Ativação de middleware baseada em fábrica no ASP.NET Core
- ativação do middleware com um contêiner de terceiros no ASP.NET Core
Por Rick Anderson e Steve Smith
Middleware é um software montado em um pipeline de aplicativos para lidar com solicitações e respostas. ASP.NET Core fornece um conjunto avançado de componentes de middleware integrados, mas em alguns cenários você pode querer escrever um middleware personalizado.
Observação
Este tópico descreve como escrever middleware baseado em convenção. Para obter uma abordagem que usa digitação forte e ativação por solicitação, consulte Ativação de middleware baseada em fábrica no ASP.NET Core.
Classe middleware
O middleware geralmente é encapsulado em uma classe e exposto com um método de extensão. Considere o seguinte middleware, que define a cultura para a solicitação atual a partir de uma cadeia de caracteres de consulta:
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}");
});
}
}
O código de exemplo anterior é usado para demonstrar a criação de um componente de middleware. Para obter o suporte interno à localização do ASP.NET Core, consulte Globalização e localização no ASP.NET Core.
Teste o middleware passando na cultura. Por exemplo, solicite https://localhost:5001/?culture=no.
O código a seguir move o delegado de middleware para uma classe:
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);
}
}
}
A classe de middleware deve incluir:
- Um construtor público com um parâmetro do tipo RequestDelegate.
- Um método público chamado
InvokeouInvokeAsync. Este método deve:- Devolver um
Taskficheiro . - Aceite um primeiro parâmetro do tipo HttpContext.
- Devolver um
Parâmetros adicionais para o construtor e Invoke/InvokeAsync são preenchidos por injeção de dependência (DI).
Dependências de middleware
O middleware deve seguir o princípio de dependências explícitas expondo suas dependências em seu construtor. O middleware é construído uma vez por tempo de vida do aplicativo. Consulte a seção Dependências de middleware por solicitação se precisar compartilhar serviços com middleware em uma solicitação.
Os componentes de middleware podem resolver suas dependências a partir da injeção de dependência (DI) por meio de parâmetros do construtor. UseMiddleware também pode aceitar parâmetros adicionais diretamente.
Dependências de middleware por solicitação
Como o middleware é construído na inicialização do aplicativo, não por solicitação, os serviços de tempo de vida com escopo usados pelos construtores de middleware não são compartilhados com outros tipos de dependência injetada durante cada solicitação. Se tiver de partilhar um serviço de âmbito limitado entre o seu middleware e outros tipos, adicione esses serviços à assinatura do método InvokeAsync. O InvokeAsync método pode aceitar parâmetros adicionais que são preenchidos por DI:
public class CustomMiddleware
{
private readonly RequestDelegate _next;
public CustomMiddleware(RequestDelegate next)
{
_next = next;
}
// IMyScopedService is injected into InvokeAsync
public async Task InvokeAsync(HttpContext httpContext, IMyScopedService svc)
{
svc.MyProperty = 1000;
await _next(httpContext);
}
}
As opções de ciclo de vida e registo contêm uma amostra completa de middleware com serviços com ciclo de vida delimitado.
Método de extensão de middleware
O seguinte método de extensão expõe o middleware através de IApplicationBuilder:
using Microsoft.AspNetCore.Builder;
namespace Culture
{
public static class RequestCultureMiddlewareExtensions
{
public static IApplicationBuilder UseRequestCulture(
this IApplicationBuilder builder)
{
return builder.UseMiddleware<RequestCultureMiddleware>();
}
}
}
O código a seguir chama o middleware de 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 adicionais
- Opções de tempos de vida e registo contém uma amostra completa de middleware com serviços de ciclo de vida: com escopo, transitórioe singleton.
- Middleware do ASP.NET Core
- Teste o middleware Core do ASP.NET
- Migrar módulos HTTP para middleware ASP.NET Core
- Inicialização do aplicativo no ASP.NET Core
- Solicitar Funcionalidades no ASP.NET Core
- Ativação de middleware baseada em fábrica no ASP.NET Core
- ativação do middleware com um contêiner de terceiros no ASP.NET Core