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 il componente successivo nella pipeline.Can perform work before and after the next component in the pipeline.

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. Quando un middleware esegue un corto circuito, viene denominato middleware terminale perché impedisce all'ulteriore middleware di elaborare la richiesta.When a middleware short-circuits, it's called a terminal middleware because it prevents further middleware from processing the request.

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 ulteriori 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 additional 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. I delegati che gestiscono le eccezioni devono essere chiamati nella prima parte della pipeline in modo che possano individuare le eccezioni che si verificano nelle parti successive della pipeline.Exception-handling delegates should be 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.");
        });
    }
}

Quando un delegato non passa una richiesta al delegato successivo, si crea un cosiddetto corto circuito della pipeline delle richieste.When a delegate doesn't pass a request to the next delegate, it's 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ò operare come middleware terminale elaborando una richiesta di un file statico ed effettuando il corto circuito della pipeline rimanente.For example, Static File Middleware can act as a terminal middleware by processing a request for a static file and short-circuiting the rest of the pipeline. Il middleware aggiunto alla pipeline prima del middleware che termina l'ulteriore elaborazione elabora comunque il codice dopo le istruzioni next.Invoke.Middleware added to the pipeline before the middleware that terminates further processing still processes code after their next.Invoke statements. Vedere comunque l'avviso seguente sul tentativo di scrivere una risposta che è già stata inviata.However, see the following warning about attempting to write to a response that has already been sent.

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
    • Quando l'app viene eseguita nell'ambiente di sviluppo:When the app runs in the Development environment:
    • Quando l'app viene eseguita nell'ambiente di produzione:When the app runs in the Production environment:
      • Il middleware del gestore delle eccezioni (UseExceptionHandler) intercetta le eccezioni generate nei middleware seguenti.Exception Handler Middleware (UseExceptionHandler) catches exceptions thrown in the following middlewares.
      • Il middleware del protocollo HSTS (HTTP Strict Transport Security) (UseHsts) aggiunge l'intestazione Strict-Transport-Security.HTTP Strict Transport Security Protocol (HSTS) Middleware (UseHsts) adds the Strict-Transport-Security header.
  2. Il middleware di reindirizzamento HTTPS (UseHttpsRedirection) reindirizza le richieste HTTP a HTTPS.HTTPS Redirection Middleware (UseHttpsRedirection) redirects HTTP requests to HTTPS.
  3. Il middleware dei file statici (UseStaticFiles) restituisce i file statici e impedisce ulteriori elaborazioni della richiesta.Static File Middleware (UseStaticFiles) returns static files and short-circuits further request processing.
  4. Il middleware dei criteri per i cookie (UseCookiePolicy) rende l'app conforme al Regolamento generale sulla protezione dei dati (GDPR).Cookie Policy Middleware (UseCookiePolicy) conforms the app to the EU General Data Protection Regulation (GDPR) regulations.
  5. Il middleware di autenticazione (UseAuthentication) tenta di autenticare l'utente prima che sia autorizzato ad accedere a risorse protette.Authentication Middleware (UseAuthentication) attempts to authenticate the user before they're allowed access to secure resources.
  6. Il middleware di sessione (UseSession) stabilisce e mantiene aggiornato lo stato sessione.Session Middleware (UseSession) establishes and maintains session state. Se l'app usa lo stato sessione, chiamare il middleware della sessione dopo il middleware dei criteri per i cookie e prima del middleware MVC.If the app uses session state, call Session Middleware after Cookie Policy Middleware and before MVC Middleware.
  7. MVC (UseMvc) per aggiungere MVC alla pipeline delle richieste.MVC (UseMvc) to add MVC to the request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();
    app.UseAuthentication();
    app.UseSession();
    app.UseMvc();
}

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.

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 segments 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 di elaborazione delle richieste e indicazioni sulle condizioni nelle quali il middleware può terminare l'elaborazione delle richieste.The Order column provides notes on middleware placement in the request processing pipeline and under what conditions the middleware may terminate request processing. Quando un middleware esegue un corto circuito della pipeline di elaborazione delle richieste e impedisce al middleware a valle di elaborare una richiesta, viene denominato middleware terminale.When a middleware short-circuits the request processing pipeline and prevents further downstream middleware from processing a request, it's called a terminal middleware. Per altre informazioni sul corto circuito, vedere la sezione Creare una pipeline middleware con IApplicationBuilder.For more information on short-circuiting, see the Create a middleware pipeline with IApplicationBuilder section.

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.
Gestione delle eccezioniException Handling Gestisce le eccezioni.Handles exceptions. 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.Redirect all HTTP requests to HTTPS. 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.Security enhancement middleware that adds a special response header. 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.Processes requests with MVC/Razor Pages. 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.

Risorse aggiuntiveAdditional resources