Configurare middleware e servizi in ASP.NET Core

di Moreno Gentili, in ASP.NET Core,

Con il rilascio di ASP.NET Core 1.0 dello scorso giugno, possiamo finalmente iniziare a costruire applicazioni web ASP.NET multipiattaforma.
Con Visual Studio 2015 Update 3 andiamo a realizzare il nostro primo progetto, selezionando il nuovo template ASP.NET Core Web Application.


Uno dei file da esaminare subito è Startup.cs che rappresenta il punto di ingresso della nostra applicazione e ci permette perciò di eseguire codice di configurazione al suo avvio. Nella classe Startup troveremo il metodo Configure, che useremo per configurare i middleware, e ConfigureServices, destinato invece alla configurazione dei servizi. Andiamo a vederli entrambi nel dettaglio.

Configurazione dei middleware

Un middleware è un componente disposto sequenzialmente nella pipeline di ASP.NET Core ed ha la facoltà di esaminare i dati della richiesta HTTP per reagire di conseguenza, ad esempio producendo un output per il client o bloccando del tutto la richiesta nel caso in cui non fosse autorizzata.
Ci siamo occupati dei middleware in precedenti script, accessibili da questa lista:
http://aspit.co/bct

Microsoft fornisce un'introduzione approfondita e accurata nel sito docs.asp.net, sito ufficiale della documentazione di ASP.NET Core.
http://aspit.co/bcu

Configurare opportunamente i middleware è un'abilita importante da acquisire perché da essa dipendono le prestazioni e la sicurezza della nostra applicazione.

Sono esempi di middleware di ASP.NET Core 1.0:

  • Il middleware di routing, usato da ASP.NET MVC per designare il controller e l'action da eseguire in base all'URL richiesto;
  • La pagina di errore di ASP.NET (che ora ha uno sfondo bianco anziché giallo), che è in grado di intercettare eccezioni nell'applicazione e presentare un messaggio di errore dettagliato;
  • Il gestore dei file statici, che mette l'applicazione in grado di servire immagini, stili CSS, javascript e ogni altro genere di file statico.

Non ci deve sorprendere il fatto che alcune funzionalità che in passato abbiamo dato per scontate (come appunto la capacità del webserver di servire i file statici) debbano ora essere riabilitate come middleware. ASP.NET Core è una tecnologia che ci rende padroni di stabilire il giusto connubio tra funzionalità e prestazioni per ogni nostra applicazione.

Nel metodo Configure (la cui presenza è obbligatoria all'interno della classe Startup), andiamo a definire i middleware usati nella pipeline di elaborazione delle richieste HTTP.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{

  // Grazie al parametro env possiamo sapere in che ambiente siamo (sviluppo, produzione o altro)
  // e usare middleware diversi in base alla situazione, per ottimizzare la nostra pipeline
  if (env.IsDevelopment())
  {
    //Mentre siamo in sviluppo, usiamo il middleware
    //che ci mostra la pagina di errore dettagliata
    app.UseDeveloperExceptionPage();
  }
  else
  {
    //Altrimenti, se siamo in produzione,
    //reindirizziamo l'utente verso una pagina di cortesia
    app.UseExceptionHandler("/Home/Error");
  }
  
  //Usiamo il middleware che consente di servire i file
  //statici al client (es. immagini jpg, stili css, script js, ecc...)
  app.UseStaticFiles();
  
  //Infine usiamo il middleware di routing per la nostra
  //applicazione ASP.NET MVC Core 1.0 definendo una route di default
  app.UseMvc(routes =>
  {
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");
  });
}

I vari middleware sono distribuiti come pacchetti NuGet. Visual Studio 2015 è in grado di suggerirci il giusto pacchetto nel caso non fosse già stato installato nel progetto.


Insieme al middleware, nel pacchetto troveremo un extension method di IApplicationBuilder che rende facile la sua configurazione.
Perciò, anche noi non dimentichiamo di definire un extension method che inizia con Use nel momento in cui andremo a scrivere e distribuire un middleware personalizzato.

Configurazione dei servizi

Si può definire "servizio" un qualsiasi componente riutilizzabile della nostra applicazione che sia in grado di offrire una funzionalità specifica o di restituire un risultato.
Esempi di servizi sono:

  • Il contesto di Entity Framework, che ci permette di accedere al database;
  • I componenti di ASP.NET MVC Core, come i filtri globali, i formatters e i model binders;
  • Eventuali oggetti incaricati di effettuare dei calcoli, spedire e-mail, accedere a web-services o altro tipo di risorse.

Per aggiungere un servizio al catalogo dell'applicazione ASP.NET Core usiamo il metodo ConfigureServices, la cui presenza è facoltativa all'interno della classe Startup. Segue un esempio di configurazione dei servizi:

public void ConfigureServices(IServiceCollection services)
{
    // Aggiungiamo il DbContext, configurando la connection string
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    // Aggiungiamo i servizi di ASP.NET Identity
    services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    // Aggiungiamo i servizi di ASP.NET MVC
    services.AddMvc();

    // Aggiungiamo altre classi per l'invio di email ed sms
    services.AddTransient<IEmailSender, AuthMessageSender>();
    services.AddTransient<ISmsSender, AuthMessageSender>();
}

Anche in questo caso sfruttiamo degli appositi extension methods che troveremo nei rispettivi pacchetti NuGet. Come si vede nell'esempio, tali metodi sono prefissati da Add, ad indicare l'aggiunta alla collezione dei servizi di cui l'applicazione può avvalersi.

Le specifice istruzioni per configurare un servizio o un middleware di terze parti andranno ricercate sul repository GitHub del progetto. Data la natura open-source di ASP.NET Core, infatti, è molto frequente trovare documentazione in questo modo. Ecco per esempio le istruzioni per configurare il servizio di logging SeriLog.
http://aspit.co/bcv

Dopo aver aggiunto i servizi in questo modo, andiamo a recuperarli nella nostra applicazione come parametri dei costruttori di alcune classi. Ad esempio, se abbiamo la necessità di usare il DbContext di Entity Framework da un nostro Controller di ASP.NET MVC Core, scriveremo:

public class UsersController : Controller
{
  private readonly ApplicationDbContext context;
  
  // Riceviamo l'istanza del DbContext come parametro del costruttore
  public UsersController(ApplicationDbContext context)
  {
    // Ne manteniamo il riferimento su un campo privato
  // per un prossimo utilizzo
    this.context = context;
  }
  
  public IActionResult Edit(string email)
  {
    // Uso l'istanza del DbContext da questa action
    var user = context.Users.SingleOrDefault(u => u.Email == email);
    return View(user);
  }
}

Aggiungere ed usare i servizi in questo modo non è obbligatorio in un'applicazione ASP.NET Core ma è utile perchè promuove il disaccoppiamento dei componenti e migliora perciò la manutenibilità del codice. Inoltre, ci evita la preoccupazione di gestire il ciclo di vita degli oggetti; un compito ora affidato al meccanismo di dependency injection integrato in ASP.NET Core.

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi