Middleware di ASP.NET CoreASP.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. Ogni componente:Each component:

  • Sceglie se passare la richiesta al componente successivo nella pipeline.Chooses whether to pass the request to the next component in the pipeline.
  • Può eseguire le operazioni prima e dopo aver chiamato il componente successivo nella pipeline.Can perform work before and after the next component in the pipeline is invoked.

Per compilare la pipeline delle richieste vengono usati i delegati di richiesta.Request delegates are used to build the request pipeline. I delegati di richiesta gestiscono ogni richiesta HTTP.The request delegates handle each HTTP request.

I delegati di richiesta vengono configurati tramite i metodi di estensione Run, Map e Use.Request delegates are configured using Run, Map, and Use extension methods. È possibile specificare un singolo delegato di richiesta inline come metodo anonimo (chiamato middleware inline) o definirlo in una classe riutilizzabile.An individual request delegate can be specified in-line as an anonymous method (called in-line middleware), or it can be defined in a reusable class. Le classi riutilizzabili o i metodi anonimi inline costituiscono il middleware o sono noti anche come componenti middleware.These reusable classes and in-line anonymous methods are middleware, also called middleware components. Ogni componente middleware è responsabile della chiamata del componente seguente nella pipeline o del corto circuito della pipeline.Each middleware component in the request pipeline is responsible for invoking the next component in the pipeline or short-circuiting the pipeline.

In Eseguire la migrazione di moduli e gestori HTTP in middleware di ASP.NET Core sono descritte le differenze tra le pipeline delle richieste in ASP.NET Core e in ASP.NET 4.x e sono riportati altri esempi di middleware.Eseguire la migrazione di moduli e gestori HTTP in middleware di ASP.NET Core explains the difference between request pipelines in ASP.NET Core and ASP.NET 4.x and provides more middleware samples.

Creare una pipeline middleware con IApplicationBuilderCreate a middleware pipeline with IApplicationBuilder

La pipeline delle richieste ASP.NET Core è costituita da una sequenza di delegati di richiesta, chiamati uno dopo l'altro.The ASP.NET Core request pipeline consists of a sequence of request delegates, called one after the other. Il diagramma seguente illustra il concetto.The following diagram demonstrates the concept. Il thread di esecuzione seguente le frecce nere.The thread of execution follows the black arrows.

Modello di elaborazione delle richieste che visualizza una richiesta in arrivo, l'elaborazione tramite tre middleware e la risposta che esce dall'app.

I delegati possono eseguire le operazioni prima del delegato successivo e dopo di esso.Each delegate can perform operations before and after the next delegate. Un delegato può anche decidere di non passare una richiesta al delegato successivo e creare un cosiddetto corto circuito della pipeline delle richieste.A delegate can also decide to not pass a request to the next delegate, which is called short-circuiting the request pipeline. Il corto circuito è spesso opportuno poiché evita l'esecuzione di operazioni non necessarie.Short-circuiting is often desirable because it avoids unnecessary work. Ad esempio, il middleware dei file statici può restituire una richiesta di un file statico ed effettuare il corto circuito della pipeline rimanente.For example, Static File Middleware can return a request for a static file and short-circuit the rest of the pipeline. I delegati che gestiscono le eccezioni vengono chiamati nella prima parte della pipeline, in modo che possano intercettare le eccezioni che si verificano nelle parti successive della pipeline.Exception-handling delegates are called early in the pipeline, so they can catch exceptions that occur in later stages of the pipeline.

L'app di ASP.NET Core più semplice imposta un delegato di richiesta singolo che gestisce tutte le richieste.The simplest possible ASP.NET Core app sets up a single request delegate that handles all requests. In questo caso non è inclusa una pipeline di richieste effettiva.This case doesn't include an actual request pipeline. Al contrario, viene chiamata una singola funzione anonima in risposta a ogni richiesta HTTP.Instead, a single anonymous function is called in response to every HTTP request.

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello, World!");
        });
    }
}

Il primo delegato Run termina la pipeline.The first Run delegate terminates the pipeline.

È possibile concatenare più delegati di richiesta insieme con Use.Chain multiple request delegates together with Use. Il parametro next rappresenta il delegato successivo nella pipeline.The next parameter represents the next delegate in the pipeline. È possibile eseguire il corto circuito della pipeline non chiamando il parametro next.You can short-circuit the pipeline by not calling the next parameter. In genere è possibile eseguire un'azione prima e dopo il delegato successivo, come illustra l'esempio seguente:You can typically perform actions both before and after the next delegate, as the following example demonstrates:

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.Use(async (context, next) =>
        {
            // Do work that doesn't write to the Response.
            await next.Invoke();
            // Do logging or other work that doesn't write to the Response.
        });

        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello from 2nd delegate.");
        });
    }
}

Avviso

Non chiamare next.Invoke dopo aver inviato la risposta al client.Don't call next.Invoke after the response has been sent to the client. Le modifiche apportate a HttpResponse dopo l'avvio della risposta generano un'eccezione.Changes to HttpResponse after the response has started throw an exception. Ad esempio, le modifiche come l'impostazione delle intestazioni e di un codice di stato generano un'eccezione.For example, changes such as setting headers and a status code throw an exception. Scrivere nel corpo della risposta dopo aver chiamato next:Writing to the response body after calling next:

  • Può causare una violazione del protocollo.May cause a protocol violation. Ad esempio, scrivere un contenuto che supera il valore Content-Length specificato.For example, writing more than the stated Content-Length.
  • Può danneggiare il formato del corpo.May corrupt the body format. Ad esempio, scrivere un piè di pagina HTML in un file CSS.For example, writing an HTML footer to a CSS file.

HasStarted è un hint utile per indicare se le intestazioni sono state inviate o se è stato scritto contenuto nel corpo.HasStarted is a useful hint to indicate if headers have been sent or the body has been written to.

OrdinamentoOrder

L'ordine in cui vengono aggiunti i componenti middleware nel metodo Startup.Configure definisce l'ordine in cui i componenti middleware vengono richiamati per le richieste e l'ordine inverso per la risposta.The order that middleware components are added in the Startup.Configure method defines the order in which the middleware components are invoked on requests and the reverse order for the response. Questo ordinamento è fondamentale per la sicurezza, le prestazioni e la funzionalità.The order is critical for security, performance, and functionality.

Il metodo Startup.Configure seguente aggiunge componenti del middleware per gli scenari di app comuni:The following Startup.Configure method adds middleware components for common app scenarios:

  1. Gestione errori/eccezioniException/error handling
  2. Protocollo HTTP Strict Transport SecurityHTTP Strict Transport Security Protocol
  3. Reindirizzamento HTTPSHTTPS redirection
  4. File server staticoStatic file server
  5. Applicazione dei criteri per i cookieCookie policy enforcement
  6. AutenticazioneAuthentication
  7. SessioneSession
  8. MVCMVC
public void Configure(IApplicationBuilder app)
{
    if (env.IsDevelopment())
    {
        // When the app runs in the Development environment:
        //   Use the Developer Exception Page to report app runtime errors.
        //   Use the Database Error Page to report database runtime errors.
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        // When the app doesn't run in the Development environment:
        //   Enable the Exception Handler Middleware to catch exceptions
        //     thrown in the following middlewares.
        //   Use the HTTP Strict Transport Security Protocol (HSTS)
        //     Middleware.
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    // Use HTTPS Redirection Middleware to redirect HTTP requests to HTTPS.
    app.UseHttpsRedirection();

    // Return static files and end the pipeline.
    app.UseStaticFiles();

    // Use Cookie Policy Middleware to conform to EU General Data 
    // Protection Regulation (GDPR) regulations.
    app.UseCookiePolicy();

    // Authenticate before the user accesses secure resources.
    app.UseAuthentication();

    // If the app uses session state, call Session Middleware after Cookie 
    // Policy Middleware and before MVC Middleware.
    app.UseSession();

    // Add MVC to the request pipeline.
    app.UseMvc();
}
  1. Gestione errori/eccezioniException/error handling
  2. File staticiStatic files
  3. AutenticazioneAuthentication
  4. SessioneSession
  5. MVCMVC
public void Configure(IApplicationBuilder app)
{
    // Enable the Exception Handler Middleware to catch exceptions
    //   thrown in the following middlewares.
    app.UseExceptionHandler("/Home/Error");

    // Return static files and end the pipeline.
    app.UseStaticFiles();

    // Authenticate before you access secure resources.
    app.UseIdentity();

    // If the app uses session state, call UseSession before 
    // MVC Middleware.
    app.UseSession();

    // Add MVC to the request pipeline.
    app.UseMvcWithDefaultRoute();
}

Nell'esempio di codice precedente, ogni metodo di estensione del middleware viene esposto in IApplicationBuilder tramite lo spazio dei nomi Microsoft.AspNetCore.Builder.In the preceding example code, each middleware extension method is exposed on IApplicationBuilder through the Microsoft.AspNetCore.Builder namespace.

UseExceptionHandler è il primo componente middleware aggiunto alla pipeline.UseExceptionHandler is the first middleware component added to the pipeline. Pertanto, il middleware del gestore di eccezioni intercetta le eccezioni che si verificano nelle chiamate successive.Therefore, the Exception Handler Middleware catches any exceptions that occur in later calls.

Il middleware dei file statici viene chiamato nella prima parte della pipeline in moda che possa gestire le richieste ed eseguire un corto circuito senza passare attraverso i componenti rimanenti.Static File Middleware is called early in the pipeline so that it can handle requests and short-circuit without going through the remaining components. Il middleware dei file statici non offre controlli di autorizzazione.The Static File Middleware provides no authorization checks. I file serviti dal sever, inclusi i file in wwwroot, sono disponibili pubblicamente.Any files served by it, including those under wwwroot, are publicly available. Vedere File statici in ASP.NET Core per un approccio alla protezione dei file statici.For an approach to secure static files, see File statici in ASP.NET Core.

Se la richiesta non è gestita dal middleware dei file statici, viene passata al middleware di autenticazione (UseAuthentication) che esegue l'autenticazione.If the request isn't handled by the Static File Middleware, it's passed on to the Authentication Middleware (UseAuthentication), which performs authentication. L'autenticazione non esegue il corto circuito di richieste non autenticate.Authentication doesn't short-circuit unauthenticated requests. Sebbene il middleware di autenticazione esegua l'autenticazione delle richieste, l'autorizzazione (e il rifiuto) si verifica solo dopo che MVC seleziona una pagina Razor o un controller specifico e un'azione.Although Authentication Middleware authenticates requests, authorization (and rejection) occurs only after MVC selects a specific Razor Page or MVC controller and action.

Se la richiesta non è gestita dal middleware dei file statici, viene passata al middleware dell'identità (UseIdentity) che esegue l'autenticazione.If the request isn't handled by Static File Middleware, it's passed on to the Identity Middleware (UseIdentity), which performs authentication. Identity non esegue il corto circuito di richieste non autenticate.Identity doesn't short-circuit unauthenticated requests. Sebbene Identity esegua l'autenticazione delle richieste, l'autorizzazione (e il rifiuto) si verifica solo dopo che MVC seleziona un controller specifico e un'azione.Although Identity authenticates requests, authorization (and rejection) occurs only after MVC selects a specific controller and action.

L'esempio seguente illustra un ordinamento del middleware nel quale le richieste dei file statici vengono gestite dal middleware dei file statici prima del middleware di compressione delle risposte.The following example demonstrates a middleware order where requests for static files are handled by Static File Middleware before Response Compression Middleware. I file statici non vengono compressi con questo ordine di middleware.Static files aren't compressed with this middleware order. Le risposte MVC da UseMvcWithDefaultRoute possono essere compresse.The MVC responses from UseMvcWithDefaultRoute can be compressed.

public void Configure(IApplicationBuilder app)
{
    // Static files not compressed by Static File Middleware.
    app.UseStaticFiles();
    app.UseResponseCompression();
    app.UseMvcWithDefaultRoute();
}

Use, Run e MapUse, Run, and Map

Configurare la pipeline HTTP usando Use,Run e Map.Configure the HTTP pipeline using Use, Run, and Map. Il metodo Use può eseguire il corto circuito della pipeline, ovvero non chiamare un delegato di richiesta next.The Use method can short-circuit the pipeline (that is, if it doesn't call a next request delegate). Run è una convenzione e alcuni componenti del middleware possono esporre metodi Run[Middleware] che vengono eseguiti al termine della pipeline.Run is a convention, and some middleware components may expose Run[Middleware] methods that run at the end of the pipeline.

Le estensioni Map vengono usate come convenzione per la diramazione della pipeline.Map extensions are used as a convention for branching the pipeline. Map* crea un ramo nella pipeline delle richieste in base alle corrispondenze del percorso della richiesta specificato.Map* branches the request pipeline based on matches of the given request path. Se il percorso della richiesta inizia con il percorso specificato, il ramo viene eseguito.If the request path starts with the given path, the branch is executed.

public class Startup
{
    private static void HandleMapTest1(IApplicationBuilder app)
    {
        app.Run(async context =>
        {
            await context.Response.WriteAsync("Map Test 1");
        });
    }

    private static void HandleMapTest2(IApplicationBuilder app)
    {
        app.Run(async context =>
        {
            await context.Response.WriteAsync("Map Test 2");
        });
    }

    public void Configure(IApplicationBuilder app)
    {
        app.Map("/map1", HandleMapTest1);

        app.Map("/map2", HandleMapTest2);

        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello from non-Map delegate. <p>");
        });
    }
}

La tabella seguente visualizza le richieste e le risposte da http://localhost:1234 usando il codice precedente.The following table shows the requests and responses from http://localhost:1234 using the previous code.

RichiestaRequest RispostaResponse
localhost:1234localhost:1234 Hello from non-Map delegate.Hello from non-Map delegate.
localhost:1234/map1localhost:1234/map1 Map Test 1Map Test 1
localhost:1234/map2localhost:1234/map2 Map Test 2Map Test 2
localhost:1234/map3localhost:1234/map3 Hello from non-Map delegate.Hello from non-Map delegate.

Quando si usa Map, i segmenti di percorso corrispondenti vengono rimossi da HttpRequest.Path e aggiunti a HttpRequest.PathBase per ogni richiesta.When Map is used, the matched path segment(s) are removed from HttpRequest.Path and appended to HttpRequest.PathBase for each request.

MapWhen crea un ramo nella pipeline delle richieste in base al risultato del predicato specificato.MapWhen branches the request pipeline based on the result of the given predicate. È possibile usare qualsiasi predicato di tipo Func<HttpContext, bool> per mappare le richieste a un nuovo ramo della pipeline.Any predicate of type Func<HttpContext, bool> can be used to map requests to a new branch of the pipeline. Nell'esempio seguente viene usato un predicato per rilevare la presenza di una variabile di stringa di query branch:In the following example, a predicate is used to detect the presence of a query string variable branch:

public class Startup
{
    private static void HandleBranch(IApplicationBuilder app)
    {
        app.Run(async context =>
        {
            var branchVer = context.Request.Query["branch"];
            await context.Response.WriteAsync($"Branch used = {branchVer}");
        });
    }

    public void Configure(IApplicationBuilder app)
    {
        app.MapWhen(context => context.Request.Query.ContainsKey("branch"),
                               HandleBranch);

        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello from non-Map delegate. <p>");
        });
    }
}

La tabella seguente visualizza le richieste e le risposte da http://localhost:1234 usando il codice precedente.The following table shows the requests and responses from http://localhost:1234 using the previous code.

RichiestaRequest RispostaResponse
localhost:1234localhost:1234 Hello from non-Map delegate.Hello from non-Map delegate.
localhost:1234/?branch=masterlocalhost:1234/?branch=master Ramo usato = masterBranch used = master

Map supporta l'annidamento, ad esempio:Map supports nesting, for example:

app.Map("/level1", level1App => {
    level1App.Map("/level2a", level2AApp => {
        // "/level1/level2a" processing
    });
    level1App.Map("/level2b", level2BApp => {
        // "/level1/level2b" processing
    });
});

Map può anche trovare la corrispondenza di più segmenti contemporaneamente:Map can also match multiple segments at once:

public class Startup
{
    private static void HandleMultiSeg(IApplicationBuilder app)
    {
        app.Run(async context =>
        {
            await context.Response.WriteAsync("Map multiple segments.");
        });
    }

    public void Configure(IApplicationBuilder app)
    {
        app.Map("/map1/seg1", HandleMultiSeg);

        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello from non-Map delegate.");
        });
    }
}

Middleware incorporatoBuilt-in middleware

ASP.NET Core include i componenti middleware seguenti.ASP.NET Core ships with the following middleware components. Nella colonna Ordinamento sono disponibili note sul posizionamento del middleware nella pipeline delle richieste e indicazioni sulle condizioni nelle quali il middleware può terminare la richiesta e impedire l'elaborazione di una richiesta da altro middleware.The Order column provides notes on the middleware's placement in the request pipeline and under what conditions the middleware may terminate the request and prevent other middleware from processing a request.

MiddlewareMiddleware DescrizioneDescription OrdinamentoOrder
AutenticazioneAuthentication Offre il supporto dell'autenticazione.Provides authentication support. Prima di HttpContext.User.Before HttpContext.User is needed. Terminale per i callback OAuth.Terminal for OAuth callbacks.
Criteri per i cookieCookie Policy Registra il consenso degli utenti per l'archiviazione delle informazioni personali e applica gli standard minimi per i campi dei cookie, come secure e SameSite.Tracks consent from users for storing personal information and enforces minimum standards for cookie fields, such as secure and SameSite. Prima del middleware che emette i cookie.Before middleware that issues cookies. Esempi: Autenticazione, Sessione, MVC (TempData).Examples: Authentication, Session, MVC (TempData).
CORSCORS Configura la condivisione di risorse tra le origini (CORS).Configures Cross-Origin Resource Sharing. Prima dei componenti che usano CORS.Before components that use CORS.
DiagnosticaDiagnostics Configura la diagnostica.Configures diagnostics. Prima dei componenti che generano errori.Before components that generate errors.
Intestazioni inoltrateForwarded Headers Inoltra le intestazioni proxy nella richiesta corrente.Forwards proxied headers onto the current request. Prima dei componenti che usano i campi aggiornati.Before components that consume the updated fields. Esempi: schema, host, IP client, metodo.Examples: scheme, host, client IP, method.
Controllo integritàHealth Check Controlla l'integrità di un'app ASP.NET Core e le relative dipendenze, come il controllo della disponibilità del database.Checks the health of an ASP.NET Core app and its dependencies, such as checking database availability. Terminale se una richiesta corrisponde a un endpoint di controllo di integrità.Terminal if a request matches a health check endpoint.
Override del metodo HTTPHTTP Method Override Consente a una richiesta POST in arrivo di eseguire l'override del metodo.Allows an incoming POST request to override the method. Prima dei componenti che usano il metodo aggiornato.Before components that consume the updated method.
Reindirizzamento HTTPSHTTPS Redirection Reindirizzare tutte le richieste HTTP a HTTPS (ASP.NET Core 2.1 o versioni successive).Redirect all HTTP requests to HTTPS (ASP.NET Core 2.1 or later). Prima dei componenti che usano l'URL.Before components that consume the URL.
Protocollo HTTP Strict Transport Security (HSTS)HTTP Strict Transport Security (HSTS) Middleware di ottimizzazione della sicurezza che aggiunge un'intestazione della risposta speciale (ASP.NET Core 2.1 o versioni successive).Security enhancement middleware that adds a special response header (ASP.NET Core 2.1 or later). Prima dell'invio delle risposte e dopo i componenti che modificano le richieste.Before responses are sent and after components that modify requests. Esempi: intestazioni inoltrate, riscrittura dell'URL.Examples: Forwarded Headers, URL Rewriting.
MVCMVC Elabora le richieste con MVC/Razor Pages (ASP.NET Core 2.0 o versione successiva).Processes requests with MVC/Razor Pages (ASP.NET Core 2.0 or later). Terminale se una richiesta corrisponde a una route.Terminal if a request matches a route.
OWINOWIN Interoperabilità con app, server e middleware basati su OWIN.Interop with OWIN-based apps, servers, and middleware. Terminale se la richiesta viene elaborata completamente dal middleware OWIN.Terminal if the OWIN Middleware fully processes the request.
Memorizzazione nella cache delle risposteResponse Caching Offre il supporto per la memorizzazione delle risposte nella cache.Provides support for caching responses. Prima dei componenti che richiedono la memorizzazione nella cache.Before components that require caching.
Compressione delle risposteResponse Compression Offre il supporto per la compressione delle risposte.Provides support for compressing responses. Prima dei componenti che richiedono la compressione.Before components that require compression.
Localizzazione della richiestaRequest Localization Offre il supporto per la localizzazione.Provides localization support. Prima dei componenti sensibili alla localizzazione.Before localization sensitive components.
RoutingRouting Definisce e vincola le route di richiesta.Defines and constrains request routes. Terminale per le route corrispondenti.Terminal for matching routes.
SessioneSession Offre il supporto per la gestione delle sessioni utente.Provides support for managing user sessions. Prima dei componenti che richiedono la Sessione.Before components that require Session.
File staticiStatic Files Offre il supporto per la gestione di file statici e l'esplorazione directory.Provides support for serving static files and directory browsing. Terminale se una richiesta corrisponde a un file.Terminal if a request matches a file.
Riscrittura dell'URLURL Rewriting Offre il supporto per la riscrittura degli URL e il reindirizzamento delle richieste.Provides support for rewriting URLs and redirecting requests. Prima dei componenti che usano l'URL.Before components that consume the URL.
Oggetti WebSocketWebSockets Abilita il protocollo WebSocket.Enables the WebSockets protocol. Prima dei componenti necessari per accettare le richieste WebSocket.Before components that are required to accept WebSocket requests.

Scrivere il middlewareWrite middleware

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((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
            return 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.

È possibile testare il middleware passando le impostazioni cultura, ad esempio http://localhost:7997/?culture=no.You can test the middleware by passing in the culture, for example http://localhost:7997/?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);
        }
    }
}

Il nome del metodo Task del middleware deve essere Invoke.The middleware Task method's name must be Invoke. In ASP.NET Core 2.0 o versioni successive il nome può essere Invoke o InvokeAsync.In ASP.NET Core 2.0 or later, the name can be either Invoke or InvokeAsync.

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

    }
}

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 per richiesta.See the Per-request 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 per richiestaPer-request 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);
    }
}

Risorse aggiuntiveAdditional resources