Esercizio: Creare middleware personalizzato

Completato

Gli sviluppatori possono creare componenti middleware personalizzati per aggiungere funzionalità a un'app ASP.NET Core. Il middleware personalizzato può essere inserito in qualsiasi punto della pipeline del middleware e può essere usato con i componenti middleware predefiniti, come illustrato in questo esempio:

Diagramma che mostra il flusso di una richiesta attraverso la pipeline.

Il team operativo di rete dell'azienda sta risolvendo i problemi di prestazioni nell'ambiente di produzione. Il team ha richiesto di implementare alcune funzionalità per supportare meglio il monitoraggio in tempo reale dell'app. L'app dovrebbe registrare i dettagli della richiesta nella console. Per ogni richiesta, deve registrare il metodo di richiesta, il percorso e il codice di stato della risposta.

In questo esercizio si crea un componente middleware personalizzato che registra i dettagli della richiesta alla console.

Aggiungere middleware personalizzato

Si modificherà ora l'app ASP.NET Core esistente in modo da includere un middleware personalizzato che registra i dettagli della richiesta alla console.

  1. Aprire il file Program.cs se non è già aperto.

  2. Inserire il codice seguente subito prima di app.Run():

    app.Use(async (context, next) =>
    {
        Console.WriteLine($"{context.Request.Method} {context.Request.Path} {context.Response.StatusCode}");
        await next(); 
    });
    

    Nel codice precedente:

    • app.Use() aggiunge un componente middleware personalizzato alla pipeline. Il componente accetta un oggetto HttpContext e un oggetto RequestDelegate come parametri.
    • Il delegato scrive il metodo di richiesta, il percorso e il codice di stato della risposta nella console.
    • await next() chiama il componente middleware successivo nella pipeline.

Testare le modifiche

  1. Premere CTRL+MAIUSC+F5 per ricompilare e riavviare l'app.

  2. Quando si apre la finestra del browser, si noti che l'URL radice visualizza "Benvenuto in Contoso!"

  3. Aggiungere /history all'URL e premere INVIO. Il browser verrà reindirizzato alla pagina /about.

  4. In Visual Studio Code premere CTRL+MAIUSC+P per aprire il riquadro comandi. Cercare e quindi selezionare Console di debug: Concentrarsi sulla visualizzazione Console di debug per passare alla scheda Console di debug nel pannello inferiore. Si notino le righe seguenti:

    GET / 200
    GET /about 200
    

    L'output della console mostra il metodo di richiesta, il percorso e il codice di stato della risposta per ogni richiesta. La prima riga mostra la richiesta per l'URL radice e la seconda riga mostra la richiesta per la pagina /about.

    Nota

    Il browser potrebbe anche richiedere /favicon.ico. Si tratta di una richiesta standard per il favicon di un sito Web e può essere ignorata.

  5. Lasciare l'app in esecuzione per l'esercizio successivo.

Cambiare l'ordine del middleware

L'app sembra funzionare, ma c'è un problema. È stata richiesta la pagina /history, ma l'output della console non lo mostra. Questo comportamento è dovuto al fatto che il componente middleware personalizzato che registra i dettagli della richiesta è stato aggiunto dopo il middleware di rewriter URL. Il middleware di rewriter URL reindirizza le richieste da /history a /about e invia la risposta mentre il componente middleware personalizzato non visualizza la richiesta. Per correggere questo errore,

  1. Spostare la riga app.Use() aggiunta immediatamente prima della riga app.UseRewriter().

    Il file completo Program.cs dovrebbe essere simile al seguente:

    using Microsoft.AspNetCore.Rewrite;
    
    var builder = WebApplication.CreateBuilder(args);
    var app = builder.Build();
    
    app.Use(async (context, next) =>
    {
        Console.WriteLine($"{context.Request.Method} {context.Request.Path} {context.Response.StatusCode}");
        await next(); 
    });
    
    app.UseRewriter(new RewriteOptions().AddRedirect("history", "about"));
    
    app.MapGet("/", () => "Hello World!");
    app.MapGet("/about", () => "Contoso was founded in 2000.");
    
    app.Run();
    

    Ora il componente middleware personalizzato viene aggiunto prima del middleware di rewriter URL. Il componente middleware personalizzato registra i dettagli della richiesta prima che il middleware di rewriter URL elabori la richiesta e la reindirizzi.

  2. Riavviare l'app e testarla come in precedenza. Questa volta, l'output Console di debug deve includere la richiesta per la pagina /history.

    GET / 200
    GET /history 200
    GET /about 200
    

    L'output della console mostra ora la richiesta per la pagina /history prima che venga reindirizzato alla pagina /about.

Correggere il codice di stato

L'app è quasi pronta, ma c'è un altro problema. Il codice di stato nell'output della console è sempre 200, anche quando l'app reindirizza la richiesta. Il codice di stato per la richiesta di /history deve essere un reindirizzamento 302. Il motivo di questo comportamento è un altro problema di ordine in cui vengono elaborati i componenti middleware.

Il componente middleware personalizzato registra i dettagli nella console, quindi chiama await next() per passare al componente middleware successivo. Il problema è che la proprietà StatusCode dell'oggetto Response viene impostata dopo che il componente middleware del terminale avvia la risposta. Cambiare il codice per risolvere il problema.

  1. Nel delegato aggiunto spostare la riga Console.WriteLine() dopo la riga await next().

    Il codice aggiornato dovrebbe essere simile al seguente:

    app.Use(async (context, next) =>
    {
        await next(); 
        Console.WriteLine($"{context.Request.Method} {context.Request.Path} {context.Response.StatusCode}");
    });
    

    Ora il componente middleware personalizzato registrerà i dettagli della richiesta dopo che il componente middleware del terminale avrà impostato il codice di stato della risposta.

  2. Riavviare e testare di nuovo la richiesta di /history. L'output Console di debug dovrebbe ora visualizzare il codice di stato corretto.

    GET / 200
    GET /history 302
    GET /about 200