Scrivere middleware di ASP.NET Core personalizzatoWrite custom ASP.NET Core middleware

Rick Anderson e Steve SmithBy Rick Anderson and Steve Smith

Il middleware è un software che viene assemblato in una pipeline dell'app per gestire richieste e risposte.Middleware is software that's assembled into an app pipeline to handle requests and responses. ASP.NET Core offre un ampio set di componenti middleware integrati, ma in alcuni scenari si potrebbe voler scrivere un middleware personalizzato.ASP.NET Core provides a rich set of built-in middleware components, but in some scenarios you might want to write a custom middleware.

Classe middlewareMiddleware class

Il middleware è in genere incapsulato in una classe ed esposto con un metodo di estensione.Middleware is generally encapsulated in a class and exposed with an extension method. Si consideri il middleware seguente, che specifica le impostazioni cultura per la richiesta corrente da una stringa di query:Consider the following middleware, which sets the culture for the current request from a query string:

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}");
        });

    }
}

Il codice di esempio precedente viene usato per illustrare la creazione di un componente middleware.The preceding sample code is used to demonstrate creating a middleware component. Per il supporto di localizzazione incorporato di ASP.NET Core, vedere Globalizzazione e localizzazione in ASP.NET Core.For ASP.NET Core's built-in localization support, see Globalizzazione e localizzazione in ASP.NET Core.

Testare il middleware passando le impostazioni cultura.Test the middleware by passing in the culture. Ad esempio, richiedere https://localhost:5001/?culture=no.For example, request https://localhost:5001/?culture=no.

Il codice seguente sposta il delegato middleware in una classe:The following code moves the middleware delegate to a class:

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 classe middleware deve includere:The middleware class must include:

  • Un costruttore pubblico con un parametro di tipo RequestDelegate.A public constructor with a parameter of type RequestDelegate.
  • Un metodo pubblico denominato Invoke o InvokeAsync.A public method named Invoke or InvokeAsync. Questo metodo deve:This method must:
    • Restituire Task.Return a Task.
    • Accettare un primo parametro di tipo HttpContext.Accept a first parameter of type HttpContext.

I parametri aggiuntivi per il costruttore e Invoke/InvokeAsync vengono popolati dall'inserimento delle dipendenze.Additional parameters for the constructor and Invoke/InvokeAsync are populated by dependency injection (DI).

Dipendenze del middlewareMiddleware dependencies

Il middleware deve seguire il principio delle dipendenze esplicite esponendo le dipendenze nel costruttore.Middleware should follow the Explicit Dependencies Principle by exposing its dependencies in its constructor. Il middleware viene costruito una volta per ogni durata applicazione.Middleware is constructed once per application lifetime. Se è necessario condividere servizi con il middleware all'interno di una richiesta, vedere la sezione Dipendenze del middleware per richiesta.See the Per-request middleware dependencies section if you need to share services with middleware within a request.

I componenti middleware possono risolvere le dipendenze dall'inserimento di dipendenze mediante i parametri del costruttore.Middleware components can resolve their dependencies from dependency injection (DI) through constructor parameters. UseMiddleware<T> può anche accettare direttamente parametri aggiuntivi.UseMiddleware<T> can also accept additional parameters directly.

Dipendenze del middleware per richiestaPer-request middleware dependencies

Poiché il middleware viene creato all'avvio dell'app e non per richiesta, i servizi di durata con ambito usati dai costruttori del middleware non vengono condivisi con altri tipi di inserimento di dipendenze durante ogni richiesta.Because middleware is constructed at app startup, not per-request, scoped lifetime services used by middleware constructors aren't shared with other dependency-injected types during each request. Se è necessario condividere un servizio con ambito tra il proprio middleware e altri tipi, aggiungere i servizi alla firma del metodo Invoke.If you must share a scoped service between your middleware and other types, add these services to the Invoke method's signature. Il metodo Invoke può accettare parametri aggiuntivi popolati dall'inserimento delle dipendenze:The Invoke method can accept additional parameters that are populated by DI:

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);
    }
}

Metodo di estensione del middlewareMiddleware extension method

Il metodo di estensione seguente espone il middleware tramite IApplicationBuilder:The following extension method exposes the middleware through IApplicationBuilder:

using Microsoft.AspNetCore.Builder;

namespace Culture
{
    public static class RequestCultureMiddlewareExtensions
    {
        public static IApplicationBuilder UseRequestCulture(
            this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<RequestCultureMiddleware>();
        }
    }
}

Il codice seguente chiama il middleware da Startup.Configure:The following code calls the middleware from Startup.Configure:

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.UseRequestCulture();

        app.Run(async (context) =>
        {
            await context.Response.WriteAsync(
                $"Hello {CultureInfo.CurrentCulture.DisplayName}");
        });
    }
}

Risorse aggiuntiveAdditional resources