Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Introduzione a ASP.NET MVC

Il framework basato sul pattern MVC e targato Microsoft
Il framework basato sul pattern MVC e targato Microsoft
Link copiato negli appunti

Il pattern MVC (Model-View-Controller) è uno dei sistemi per organizzare il reperimento e la rappresentazione delle informazioni all'interno di una applicazione, che risulterà divisa in tre distinti livelli:

  • Model: contiene il database e si occupa dell'accesso a basso livello ai dati;
  • Controller: livello intermedio che gestisce gli eventi generati dall'utente, come la richiesta di una pagina da visualizzare, ed interagisce con il Model per reperire le informazioni richieste;
  • View: interfaccia grafica, sarà questo livello ad essere mostrato all'utente (nel nostro caso la pagina web).

Strutturare la nostra applicazione secondo questo schema permette di mantenere separata la logica di accesso ai dati da quella di visualizzazione degli stessi, secondo un'organizzazione che ricorda molto i tre livelli di Data Access Layer (DAL), Business Logic Layer (BLL) e User Interface Layer (UIL).

MVC è supportato da diversi framework (per esempio Ruby on Rails) ed è molto usato nello sviluppo di applicazioni Web per il commercio elettronico, blogging, etc.

In ASP.NET questa funzionalità è stata implementata con le ASP.NET 3.5 Extensions (non ancora rilasciate in versione definitiva), di cui è disponibile una versione di anteprima scaricabile da qui. Una volta terminato il download, è sufficiente avviare l'installazione guidata per configurare ASP.NET ed IIS. Il pacchetto include anche i file di progetto per Visual Studio.

Alla fine dell'articolo verrà realizzata una piccola applicazione di esempio per prendere confidenza con la nuova tecnologia, che cominciamo ora a conoscere partendo dalla particolare organizzazione dei file che la contraddistingue.

Figura 1. Struttura delle cartelle
Struttura delle cartelle

Nei progetti ASP.NET MVC esistono tre cartelle principali in cui inserire i file:

  • /Controllers
  • /Models
  • /View

Nella prima andranno inserite le classi controller, nella seconda le model (come Example.db, una classe LINQ to SQL che utilizzeremo nel nostro esempio) e nella terza le view.

Per la cartella /View è necessario spendere due parole in più: al suo interno non sono infatti direttamente contenute le classi, che sono invece posizionate in sottocartelle. Il motivo di questa ulteriore suddivisione è il ruoting degli URL che verrà spiegato nel prossimo paragrafo. Per ora ci basti notare come il nome delle sottocartelle riflette quello dei controller: HomeController.cs verrà associato alle viste presenti nella cartella Home, ProductsController.cs alle view contenute in Products e così via. L'unica directory non legata a questa regola è Shared, al cui interno devono essere memorizzati tutti i file condivisi fra più viste, come le master page.

La gerarchia appena illustrata non è obbligatoria, ma è caldamente consigliata per mantenere il progetto ordinato e leggibile.

URL Routing

Quando un client richiede una pagina al server, IIS associa l'URL ad un file .aspx ed esegue le istruzioni contenute al suo interno per poi inviare il codice HTML di risposta al client. Con MCV, invece, il server non associa più l'URL ad un file fisico, ma ad una classe Controller che si preoccupa di richiamare la vista necessaria a generare la risposta. È quindi necessario un sistema di mappatura degli URL.

In ASP.NET il funzionamento di questo meccanismo può essere modificato a proprio piacimento. Esiste comunque una regola di default: se per esempio viene richiesta la pagina /Products/List/RAM, ASP.NET richiama il metodo List, definito all'interno della classe ProductsController, passando RAM come argomento.

Esempio di metodo richiamato da URL

[ControllerAction]
public void List(string category)
{
  List<Product> products = context.GetProductsByCategory(category);

  RenderView("ProductsByCategory", products);
}

Notate la presenza dell'attributo ControllerAction e, al termine della procedura, la chiamata al metodo RenderView. Quest'ultimo è molto importante in quanto richiama la View (in questo caso ProductsByCategory.cs) che si occuperà di visualizzare i dati.

Le regole di routing predefinite di ASP.NET MVC si trovano all'interno del file Global.asax.

Regole di routing nel Global.asax

RouteTable.Routes.Add(new Route
  {
    Url = "[controller]/[action]/[id]",
    Defaults = new { action = "Index", id = (string)null },
    RouteHandler = typeof(MvcRouteHandler)
  });

RouteTable.Routes.Add(new Route
  {
    Url = "Default.aspx",
    Defaults = new { controller = "Home", action = "Index", id = (string)null },
    RouteHandler = typeof(MvcRouteHandler)
  });

Tutti gli URL che abbiamo visto finora seguono la prima regola (/Controller/Azione/Argomenti). La seconda serve invece a collegare la cartella root del sito internet al controller HomeController.

La potenza di questo sistema consiste anche nella possibilità di definire regole di URL Routing personalizzate, argomento che tuttavia esula dagli scopi di questo articolo.

L'applicazione di esempio

Nel nostro esempio vedremo come realizzare un semplicissimo catalogo di prodotti utilizzando i concetti fin qui esposti. L'applicazione visualizzerà una lista delle categorie presenti nel database e permetterà di navigare tra i prodotti in esse contenute. Invito a scaricare il file disponibile con l'articolo come riferimento.

Il database è costituito da due tabelle: Products e Categories. Per l'accesso ai dati utilizzeremo LINQ to SQL, soprattutto per la rapidità di realizzazione consentita da questa nuova tecnologia. Avremmo potuto comunque utilizzare anche metodi più "classici" quali ADO.Net e Dataset. La struttura dei dati e quindi delle classi derivate è molto semplice:

Figura 2. Diagramma delle classi
Diagramma delle classi

Ho scelto di utilizzare nomi in inglese perché il designer LINQ to SQL di Visual Studio (almeno nella versione inglese che utilizzo) gestisce automaticamente i singolari e plurali. Se avessi usato nomi italiani sarebbero saltate fuori parole come "Prodottis" e simili.

Per velocizzare le operazioni di accesso ai dati, creiamo due metodi di aiuto all'interno della classe ExampleDataContext:

public partial class ExampleDataContext
{
  public List<Category> GetCategories()
  {
    return Categories.ToList();
  }

  public List<Product> GetProductsByCategory(string category) {
    return Products.Where(c => c.Category.Name == category).ToList();
  }
}

Il primo restituisce una lista di categorie, mentre il secondo i prodotti di una singola categoria.

Per evitare di occupare l'home page del nostro sito direttamente con il catalogo dei prodotti, renderemo quest'ultimo raggiungibile all'URL /Products/. Aggiungiamo quindi una nuova classe chiamata ProductsController.cs nella cartella /Controllers.

public class ProductsController : Controller
{
  ExampleDataContext context = new ExampleDataContext();

  [ControllerAction]
  public void Index()
  {
    List<Category> categories = context.GetCategories();

    RenderView("Categories", categories);
  }

  [ControllerAction]
  public void List(string category)
  {
    List<Product> products = context.GetProductsByCategory(category);

    RenderView("ProductsByCategory", products);
  }
}

La classe, che eredita da System.Web.Mvc.Controller, possiede i metodi Index e List, che rappresentano le azioni richiamate rispettivamente dagli URL /Products/ e /Products/List/Nome_Categoria. Notate come i dati estratti dal database vengono passati alla vista, che si occuperà della loro visualizzazione, tramite il secondo argomento del metodo RenderView.

Una vista è una semplice pagina .aspx, che tuttavia non eredita (come siamo abituati) dalla classe System.Web.Page ma da System.Web.Mvc.ViewPage. Questa differenza è fondamentale perché la seconda classe offre alcune proprietà aggiuntive, tra le quali ViewData è la più importante, perché contiene i dati passati dal Controller.

Avremo bisogno di due view per mostrare i dati: Categories.aspx e ProductsByCategories.aspx. Per motivi di spazio analizzeremo dettagliatamente soltanto la prima. Ad ogni modo la logica di funzionamento della seconda non è molto diversa e non dovrebbe presentare particolari problemi.

Uno sguardo al code behind della pagina ci permette di vedere come i dati siano passati alla view in modo fortemente tipizzato:

public partial class Categories : ViewPage<List<Category>>
{
 public void Page_Load() { }
}

Per visualizzare i dati è possibile utilizzare sia controlli lato server come il nuovo ListView, che codice in linea:

<h2>Categorie:</h2>
<ul>
 <% foreach (var cat in ViewData)
   { %>
    <li><%= Html.ActionLink(cat.Name, new { action="List", id=cat.Name }) %></li>
 <% } %>
</ul>

Il metodo Html.ActionLink crea un link all'URL che richiama l'azione List del ProductController, passando come parametro il nome della categoria di cui vogliamo visualizzare i prodotti. L'URL generato sarà, come visto precedentemente, del tipo: /Products/List/Nome_Categoria.
Attraverso lo stesso metodo è possibile anche cambiare controller:

<%= Html.ActionLink("Torna alla Home Page", new { controller = "Home" }) %>

Con questo codice generiamo un link alla cartella root del sito.

Conclusioni

Abbiamo cominciato a conoscere il nuovo Framework ASP.NET MVC, una tecnologia introdotta con le ASP.NET 3.5 Extensions che ci permette di dividere, in applicazioni fortemente dipendenti da database, l'accesso ai dati dalla loro visualizzazione. Abbiamo inoltre cominciato a prendere confidenza con il meccanismo di URL Routing e con la creazione di view e controller. In un prossimo articolo vedremo come utilizzare MVC per l'aggiornamento e l'inserimento di dati nel database.

Ti consigliamo anche