Nel precedente articolo intitolato ASP.NET Core Middleware abbiamo parlato di cosa sono i middleware ed abbiamo visto come usare i middleware buit-in di Microsoft.

Ora vediamo come implementare un semplice custom Middleware che dovrà gestire una blacklist di pagine, se la pagina richiesta si trova all’interno dell’elenco si dovra rispospondere con uno status 404 (page not found).

Per prima cosa creiamo un progetto .Net Core di tipo Class Library

NewProject

ed andiamo ad aggiungere una classe che andiamo a nominare BlackListMiddleware.

La classe BlackListMiddleware sarà il nostro middleware.

NewClass

Andiamo ad aggiungere il costruttore alla classe appena creata, il costruttore avrà un parametro che chiameremo next di tipo RequestDelegate che verrà iniettato con una dependency injection direttamente da Asp.Net, il parametro next è il puntatore al prossimo middleware della pipeline da eseguire.

    public class BlackListMiddleware
    {
        RequestDelegate _next;
        public BlackListMiddleware(RequestDelegate next)
        {
            _next = next;
        }
    }
  

Per poter essere invocato il nostro middleware deve esporre un metodo che dobbiamo chiamare Invoke, nel quale andiamo ad implementare la logica di business.

        public async Task Invoke(HttpContext context)
        {
            var urlToCheck = context.Request.Path;
            if (_urlBlackList.Any(p => urlToCheck.StartsWithSegments(p)))
            {
                context.Response.StatusCode = 404;
            }
            else
            {
                await this._next.Invoke(context);
            }
        }
  

Essendo un progetto dimostrativo la logica di gestione degli indirizzi è semplifcato al massimo e gestito con una lista di stringhe statiche denominato urlToCheck.

Terminata la scrittura del metodo invoke dobbiamo inserire il middleware appena scritto all’interno della pipeline di ASP.NET Core. Procediamo aggiungendo alla nostra soluzione un progetto ASP.NET MVC Core, utilizzando il template di default , che chiameremo BlackListMiddleware.Web.

NewProjectWeb

Per inserire il nostro middleware all’interno della pipeline del nuovo progetto web creato dobbiamo modificare la classe di Startup, del progetto BlackListMiddleware.Web, in questo modo

        public void Configure(IApplicationBuilder app)
        {
            app.UseMiddleware<BlackListMiddleware>();
            app.UseStaticFiles();
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
  

A questo punto non ci resta che fare un test, compiliamo ed avviamo la soluzione; selezionando la voce about dal menu dell’applicazione avviata mi aspetto che la risposta sia “404 Page not found”. Il nostro middleware ha fatto il suo lavoro.

Il middleware ora è pronto ad essere utilizzato, possiamo pubblicarlo su nuget e renderlo pubblico, ma prima dobbiamo fare una piccola modifica.

E’ buona prassi creare un’extention alla classe IApplicationBuilder che si occuperà di registrare il nostro middleware all’interno della pipeline, di seguito un esempio:

    public static class BlackListMiddlewareBuilderExtention
    {
        public static IApplicationBuilder UseBlackList(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<BlackListMiddleware>();
        }
    }
  

così la nostra classe di startup diventa:

        public void Configure(IApplicationBuilder app)
        {
            app.UseBlackList();
            app.UseStaticFiles();
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
       
  

Ed eccoci giunti al termine il nostro middleware ora e pronto ad essere pubblicato su nuget per la distribuzione, potete trovare il codice sorgente di questo articolo nel mio repository GitHub qui.

Non mi resta che salutarvi ed augurarvi buon divertimento alla scoperta dei middleware e…….

happy coding !!!


"Middleware are software components that are assembled into an application pipeline to handle requests and responses. Each component chooses whether to pass the request on to the next component in the pipeline, and can perform certain actions before and after the next component is invoked in the pipeline. Request delegates are used to build the request pipeline. The request delegates handle each HTTP request."

Questa la definizione ufficiale di Microsoft di cosa è un middleware.

A prima vista la definizione non ci colpisce perchè ha un'aria di cosa già vista, e di fatto non siamo molto lontani dalla realtà, il concetto di middleware non è un concetto nuovo, l'abbiamo già visto in quello che conosciamo come handler http ( i quali si inserivano all'interno della pipeline di esecuzione di ASP.NET).

request-delegate-pipeline

Cosa è cambiato di fatto e perchè si parla così forte di middleware?

Essendo cambiato profondamente Asp.Net con la nuova implementazione Asp.Net Core e non essendo più quel sistema monolitico che era in passato, quale poteva essere il miglior modo di rendere modulare lo sviluppo di applicazioni? La risposta è utilizzando i middleware. Asp.Net Core è un insieme di moduli ed ogni modulo è un middleware che si inserisce all'interno della pipeline di esecuzione delle richieste HTTP di Asp.Net.

Il concetto funzionale del middleware è semplice, prende in input una richiesta HTTP ed esegue il codice per il quale è stato creato, a questo punto o restituisce una risposta HTTP, interrompendo la catena di esecuzione, oppure eseguire il middleware successivo della pipeline.

Possiamo catalogare i middleware in 4 differenti tipologie,

  • Response editing : interviene direttamente sul contenuto della risposta.
  • Request editing : il middleware di tipo  Request-Editing interviene direttamente sulla request ed esegue il prossimo middleware della catena
  • Short-Circuiting : il middleware di tipo Short Circuiting  interviene sulla risposta impostando lo stato ( 404, 403 ) ed interrompendo la catena di esecuzione dei middleware
  • Content : il middleware di tipo content interviene direttamente sulla risposta restituendo un contenuto ed interrompe la catena di esecuzione dei middleware

      MiddlewareType

      La suddivisione identificata è solo una suddivisione logica, nel momento in cui andiamo ad implementare il nostro middleware non dobbiamo necessariamente scegliere quale tipo implementare in quanto non impatta sulla scrittura del codice.

      Attualmente microsoft ha implementato e rilasciato già un set di built-in middleware che sono scaricabili tramite NuGet, di seguito l’elenco :

      • Autentication:
        Supporto per autenticazione
      • Cors:
        Configura Cross-Origin-Resource-Sharing
      • Response Caching:
        Supporto per le risposte da cache
      • Response Compression:
        Supporto per la risposta compressa
      • Routing:
        Gestione del routing
      • Session:
        Gestione della session
      • Static File:
        Supporto per la gestione dei file statici e del directory browsing
      • UrlRewrite:
        Supporto per il rewrite Urls e redirect request

      Ora che abbiamo capito come funzionano i Middleware, andiamo a vedere come possiamo configurare la pipeline, e come specificare un ordine di esecuzione.

      I middleware, come la maggior parte dei componenti che andiamo ad utilizzare all’interno delle nostre applicazioni Net Core, vengono configurati all’interno del metodo Configure della classe “Startup”.

      public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
              {
                  loggerFactory.AddConsole(Configuration.GetSection("Logging"));
                  loggerFactory.AddDebug();
      
                  app.UseApplicationInsightsRequestTelemetry();
      
                  if (env.IsDevelopment())
                  {
      Technorati Tags:
      app.UseDeveloperExceptionPage(); app.UseBrowserLink(); }
      else { app.UseExceptionHandler("/Home/Error"); } app.UseApplicationInsightsExceptionTelemetry(); app.UseStaticFiles(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); }
       

      Come possiamo vedere dall’esempio i middleware che la nostra applicazione utilizza sono diversi. In questo caso il primo middleware ad essere eseguito sarà UseApplicationInsightsRequestTelemetry, e l’ultimo della pipeline sarà UseMvc.

      E' possibile inserire delle condizioni per la manipolazione della pipeline, nel nostro caso se ci troviamo in ambiente di Development verranno inseriti nella pipeline UseDeveloperExceptionPage e UseBrowserLink, altrimenti verrà utilizzato UseExceptionHandler. Possiamo concludere dicendo che i middleware devono essere configurati all’interno della classe di Startup e l’ordine in cui vengono inseriti è esattamente l’ordine che viene utilizzato nell’esecuzione.

      Ora che abbiamo le basi per configurare i Middleware built-in di microsoft, non perdetevi il prossimo articolo dove vedremo, con un esempio pratico, come scrivere un middleware personalizzato.


      Calendar

      <<  November 2017  >>
      MonTueWedThuFriSatSun
      303112345
      6789101112
      13141516171819
      20212223242526
      27282930123
      45678910

      View posts in large calendar

      Category list