01 Mar

Le convenzioni definite nel framework ASP.NET MVC

Programming - ASP.NET MVC

Rieccoci a scrivere di ASP.NET MVC e del suo pattern Model-View-Controller. Vengono qui descritte le principali convenzioni da seguire durante lo sviluppo dell’applicazione web.

HomeController

Per convenzione l’HomeController è il punto di partenza dell’applicazione MVC. In un nuovo progetto Visual Studio crea una route di default seguendo questa convenzione. E’ sempre  possibile modificare a posteriori questa route di default nel file Global.asax.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace MvcApplication1
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default",
                "{controller}/{action}/{id}",
                new { controller = "Home", action = "Index", id = "" }
            );

        }

        protected void Application_Start()
        {
            RegisterRoutes(RouteTable.Routes);
        }
    }
}

 Models

Per convenzione, i Models vengono sempre riposti nella cartella ~/Models.

Controllers

Per convenzione, i Controllers vengono riposti nella cartella ~/Controllers. Le classi Controller hanno i nomi terminanti in “Controller”. Si prenda ad esempio la classe HomeController. Quando si utilizzano gli HTML Helper methods di Razor, per convenzione si specifica il nome senza suffisso (nel caso sopre “Home”). Il framework MVC appenderà in automatico la desinenza “Controller” nella ricerca della classe.

Views

Per convenzione, Views  e Partial Views vengono riposte nella cartella ~/Views/[ControllerName].

 Naming convention per View e azioni

Le View sono associate alle azioni attraverso una convenzione nominale. Quindi, ad esempio, se l’azione di un Controller Home è definita come Index, il framework MVC associerà la View  a partire dal file ~/View/Home/Index.[ext]. Nel caso non dovesse trovare il file in questione, lo cercherà in seconda istanza nella cartella Shared, ovvero ~/View/Shared/Index.[ext]. Le estensioni permesse saranno quelle mappate su  IIS o Web.Config.

Quindi, per convenzione, le View  prendono il nome dell’azione e vengono create in una cartella col nome del Controller.

Naming convention per i Layout

Per convenzione ai file di Layout viene sempre anteposto il prefisso_“.  Ad esempio,  _Layout.

Layout di default

Se nella View non viene specificato un Layout tramite la direttiva di Razor @Layout, il framework MVC assume il file ~/Views/Shared/_Layout.cshtl come Layout di default. Questa convenzione di default  puo’ tuttavia essere modificata nel ~/Views/_ViewStart.cshtml cambiandone il nome del file mappato dalla direttiva Razor @Layout.

Contenuti statici e template grafici

I contenuti statici come immagini, file CSS e altri vengono sempre riposti nella cartella Content.

Default request root

Per convenzione una chiamata alla root del sito viene reindirizzata verso l’azione Index dell’HomeController. Ad esempio, se http://www.sviluppoeweb.it  fosse realizzato in ASP.NET MVC, la chiamata alla home del sito verrebbe veicolata dall’HomeController verso l’azione Index e rendendo la View  ~/Views/Home/Index.cshtml.

Cartelle di sistema

Esistono cartelle convenzionali in ASP.NET. Il framework ASP.NET MVC ne eredita alcune e ne implementa di nuove. In particolare:

  • ~/App_Data: questa cartella contiene fonti dati private alla web application (xml di configurazione, db, csv, ecc). I file contenuti in questa cartella sono protetti e non accessibili pubblicamente dal sito.
  • ~/App_Start: contiene i file di configurazione principali, come le Routes, i Filters e i Bundles
  • ~/bin: contiene gli assembly compilati
  • ~/Content: contiene i file statici e i template grafici
  • ~/Controllers: contiene i Controllers
  • ~/Models: contiene i Models
  • ~/Scripts: contiene le librerie Javascript
  • ~/Views: contiene le Views, le Partial Views e i Layout
  • ~/Views/Shared: contiene le Views, le Partial Views e i Layout condivisi
  • ~/Areas: contiene le Areas, una tecnica per suddividere l’applicazione in moduli distinti
  • ~/App_GlobalResources: contiene i resource files globali (per le Web Forms)
  • ~/App_LocalResources: contiene i resource files locali (per le Web Forms)

File di sistema

Come per le cartelle, esistono anche alcuni file di sistema:

  • ~/Views/Web.Config: questo file di configurazione previene che le views vengano servite  da IIS
  • ~/Global.asax: la classe globale delle applicazioni ASP.NET (eventi di inzializzazione, shutdown, gestione delle eccezioni a livello globale, ecc. )
  • ~/Web.Config: file di configurazione dell’applicazione
23 Gen

Microsoft si cambia: benvenuto .NET Core 1.0

Programming - .NET Core 1.0

I recenti rilasci di Windows 10 e  Visual Studio 2015 hanno introdotto moltissime novità e miglioramenti sulle piattaforme di sviluppo Microsoft. Si pensi alla Universal Windows Platform (UWP), al nuovo browser EDGE,  ad una console dei comandi migliorata, ad un package managment tool (OneGet) integrato nella powershell, a Windows 10 IoT per Rasperry Pi e Arduino, e molto molto altro ancora.

Ma con tutte queste novità, a chi non è venuto qualche dubbio? Una delle cose che hanno creato non poche perplessità  riguardava le differenze tra il .NET Framework 4.6 e il .NET Framework 5.  Molti inizialmente hanno creduto che la versione 5 fosse la release successiva alla 4.6 e che quindi quest’ultima diventasse obsoleta.

In verità, come spiega molto bene Scott Hanselman nel suo blog,  la versione 5 non rappresenta una versione successiva di .NET ma una vera e propria build indipendente supportata da librerie e moduli spesso diversi rispetto a quelli della versione 4.6.

Nel 2014 Microsoft annunciò l’intenzione di rendere il framework .NET “open source and cross platform” con il rilascio di Visual Studio 2015. Per realizzare questo intento sono state riviste e a volte risviluppate ex-novo parte delle librerie .NET.

Quote - Phil Karlton

La scelta del nome del nuovo framework però non è stata azzeccatissima, creando non poca confusione tra gli sviluppatori. Per questo motivo Microsoft ha deciso di rinominare la “piattaforma” 5 (o 2015), e tutti i progetti che vi si poggiano sopra, in Core 1.0. Questo cambiamento dovrebbe evidenziare un nuovo ciclo di sviluppo incentrato su principi open source e cross platform.  Non si tratta quindi della continuazione di un “brand” già affermato, supportato, stabile e in pieno sviluppo.

Il .NET Framework 5 viene quindi rinominato in .NET Core 1.0 e tra i progetti più seguiti ASP.NET 5 prende il nome di  ASP.NET Core 1.0, Entity Framework 7 diventa Entity Framework Core 1.0,  ASP.NET Identity 3 cambia in ASP.NET Identity Core 1.0.

Questa immagine può aiutare a inquadrare le nuove “naming conventions” e a fugare ogni dubbio.

19 Gen

Bundling in un progetto ASP.NET MVC

Programming - ASP.NET MVC

Google Translate traduce la parola “bundle”  in “impacchettare”. Niente di più azzeccato per introdurre il bundling in un’applicazione ASP.NET MVC.

Oggi sviluppare siti e applicazioni per il web risulta un’attività estremamente complessa. Esistono svariati moduli open source facilmente integrabili durante lo sviluppo. Si pensi alle migliaia di librerie javascript disponibili (JQuery, Backbone.js, Knockout.js… e chi più ne ha più ne metta) o ai frameworks CSS (tra i quali spiccano Bootstrap e Zurb Foundation).

A questi moduli si aggiungono i tools di supporto allo sviluppo:  generatori di codice (Sass, Less, Coffescript, Handlebars, Jade,…), task manager (ad esempio Grunt, Gulp, Broccoli, Browserify), package manager (Nuget, Npm, Bower, ecc.) e molti altri ancora.

Quando bisogna integrare moduli esterni in un progetto web, gli sviluppatori si affidano a procedure di bundling. Queste ci assistono nell’ottimizzazione del codice.

Tra gli aspetti più importanti del bundling ci sono l’aggregazione e l’ottimizzazione dei diversi sorgenti in un unico file evitando di sovraccaricare le comunicazioni client-server (I/O overhead). Nello sviluppo web, al bundling si associa infatti un processo di “minificazione” con lo scopo di ridurre le dimensioni dei dati scambiati tra le chiamate. Grazie al bundling vengono eliminate le parti superflue o ridondanti di un file, come ad esempio spazi, commenti, ritorni a capo, ecc.

Nei progetti ASP.NET MVC le procedure di bundlig vengono gestite in tre passi:

  1. Configurazione: si istruisce l’applicazione su come combinare e comprimere i file;
  2. Registrazione: si informa l’applicazione dell’esistenza dei bundles;
  3. Reference: si referenziano i bundles nelle View di progetto e quindi nel frontend.

Vediamo nel dettaglio queste tre fasi.

Configurare i bundles

La configurazione dei bundles viene attuata nel file BundleConfig.cs riposto nella cartella  App_Start . La configurazione consiste nel definire e aggiunegere i bundles alla tabella dei bundles.

Nell’esempio qui sotto vengono inclusi tre file javascript  e due fogli di stile:

 
public static void RegisterBundles(BundleCollection bundles)
{
  //Scripts js
  var myBundleScript = new ScriptBundle("~/bundles/main-js");
  myBundleScript.Include(
    "~/Scripts/cls/clsRollingDiv.js",
    "~/Scripts/cls/clsRollingBanner.js",
    "~/Scripts/main-dev.js");

  //Cascade Styles
  var myBundleCss = new StyleBundle("~/bundles/main-css");
  myBundleCss.Include(
    "~/Content/css/css1.js",
    "~/Content/css/css2.js");
  
  //Aggiungo a BundleTable
  bundles.Add(myBundleScript);
  bundles.Add(myBundleCss);
}

Da notare che, a seconda del tipo di file, vengono utilizzate due diverse classi .NET: ScriptBundle per i file javascript e StyleBundle per i fogli di stile.

Il metodo Include  può essere sostituito dal corrispettivo IncludeDirectory che comprenderà tutti i file presenti in una cartella evitando così di elencare i file singolarmente. In entrambi i casi, alla chiamata viene passato il path dei file che si vogliamo impacchettare.

Il simbolo ~ rappresenta la root  di progetto. Questo shortcut risulta comodissimo quando passiamo da un ambiente di sviluppo ad uno di produzione. A titolo di esempio, durante lo sviluppo lo shorcut puo’ indicare una root del tipo http://localhost:1234/js/[files] mentre in produzione i file vengono ricercati in http://www.miosito.it/Scripts/[files]. Questo switch viene gestito autonomamente da ASP.NET.

Registrare i bundles

Terminata la configurazione, si passa alla registrazione dei bundles. Questa avviene nella procedura  Application_Start del file  Global.asax del nostro progetto ASP.NET MVC:

  protected void Application_Start()
    {
      AreaRegistration.RegisterAllAreas();
      [...]
      BundleConfig.RegisterBundles(BundleTable.Bundles);
    }

Con il semplice comando BundleConfig.RegisterBundles tutti i bundles vengono inclusi nella BundleTable e registrati nel progetto.

Referenziare i bundles

L’ultimo step consiste nel referenziare i bundles nelle View del nostro progetto MVC. I bundle devono quindi essere configurati pensando al loro reale utilizzo nel frontend e  nelle pagine web.

Per i file molto utilizzati (come ad esempio le librerie Bootstrap in un progetto responsive) è meglio referenziare i bundle nelle View condivise (Shared). E’ invece preferibile isolare i file meno utilizzati in bundle indipendenti  e richiamali nelle singole View. Nell’esempio sotto, richiamiamo un bundle secondario in una View non condivisa:

    
<!DOCTYPE html>
<html class="no-js" lang="en">
<head>
  <meta charset="utf-8" />
  [...]
  @Styles.Render("~/bundles/secondary-css")
</head>
<body>
  [...]
  @Scripts.Render("~/bundles/secondary-js")
</body>
</html>

Testare il comportamento dei bundles

Ora che abbiano capito come funzionano i bundle,  proviamo a testarne il comportamento. Per il test ipotizziamo di aver creato un bundle per le librerie di JQuery. Lanciamo Visual Studio e analiziamo le chiamate HTTP avvalendoci di Firefox e Firebug.

Notiamo subito che l’ottimizzazione dei file avviene solo quando simuliamo l’ambiente di produzione – quindi col parametro debug=false . Nella figura si nota l’impachettamento e l’ottimizzazione delle librerie JQuery in un ipotetico ambiente di produzione:bundles_jquery_prod

Quando lanciamo il progetto in modalità sviluppo – debug=true –  le librerie vengono restitutite senza alcuna ottimizzazione così da semplificare l’eventuale debugging. E infatti, nell’esempio proposto, viene inoltrato il file originale contenuto nella cartella degli Scripts della nostra applicazione ASP.NET MVC:bundles_jquery_debug

Conclusioni

Una corretta impostazione dei bundle comporta notevoli vantaggi, ovvero:

  1.  Ridurre le chiamate HTTP grazie all’aggregazione dei file;
  2. Ridurre le dimensioni dei file, e quindi il traffico, grazie al processo di “minificazione”;
  3. Caching dei dati inoltrati.

Il caching è particolarmente interessante. In un’applicazione ASP.NET MVC il processo di bundle setta l’header HTTP Expires ad un anno da quando il bundle è stato creato.  Quando si naviga verso una pagina precedentemente visitata non viene quindi inoltrato alcun dato ma vengono utilizzati i dati conservati nella cache del browser.

A livello statistico, Microsoft dichiara notevoli miglioramenti quando si introduce il bundling in un’applicazione:

Uso Con Bundle Senza Bundle Variazione
File Requests 9 34 256%
KB Inviati 3.26 11.92 266%
KB Ricevuti 388.51 530% 36%
Tempo Attesa 510 MS 780 MS 53%
Riferimento: Microsoft ASP.NET Blog

La tabella mostra tutta la convenienza di utilizzare procedure di bundling nelle nostre applicazioni ASP.NET MVC. Buona programmazione!

 

10 Gen

Microsoft termina il supporto ai .NET Framework 4, 4.5 e 4.5.1

System - Microsoft .NET

Il 12 Gennaio 2016 terminerà il supporto alle versioni 4.0, 4.5 e 4.5.1 del .NET Framework. Per continuare a ricevere supporto tecnico e update di sicurezza, Microsoft raccomanda di aggiornare i vari progetti alla versione piu’ recente 4.5.2.

La versione 4.6 rilasciata di recente introduce importanti novità nel framework e, se possibile, potrebbe essere la miglior scelta in eventuali migrazioni di  versione.

Tutte le versioni precedenti alla 4, ed in particolare la  2.x e la 3.5.x, continueranno invece ad essere supportate.