Condividi tramite


Parte 3: Visualizzazioni e ViewModel

di Jon Galloway

MVC Music Store è un'applicazione di esercitazione che introduce e spiega in modo dettagliato come usare ASP.NET MVC e Visual Studio per lo sviluppo Web.

MVC Music Store è un'implementazione di negozio di esempio leggera che vende album musicali online e implementa l'amministrazione del sito di base, l'accesso utente e la funzionalità del carrello acquisti.

Questa serie di esercitazioni illustra in dettaglio tutti i passaggi eseguiti per compilare l'applicazione di esempio MVC Music Store ASP.NET. La parte 3 illustra Visualizzazioni e ViewModels.

Finora abbiamo appena restituito stringhe dalle azioni del controller. Questo è un buon modo per ottenere un'idea di come funzionano i controller, ma non è come si vuole creare un'applicazione Web reale. Si vuole un modo migliore per generare il codice HTML nei browser che visitano il nostro sito, uno in cui è possibile usare i file di modello per personalizzare più facilmente il contenuto HTML di invio indietro. È esattamente ciò che le visualizzazioni fanno.

Aggiunta di un modello di visualizzazione

Per usare un modello di visualizzazione, verrà modificato il metodo HomeController Index per restituire un Oggetto ActionResult e avere visualizzato View(), come illustrato di seguito:

public class HomeController : Controller
{
    //
    // GET: /Home/
    public ActionResult Index()
    {
        return View();
    }
}

La modifica precedente indica che invece di restituire una stringa, si vuole invece usare una "Visualizzazione" per generare un risultato indietro.

Verrà ora aggiunto un modello di visualizzazione appropriato al progetto. A tale scopo, verrà posizionato il cursore di testo all'interno del metodo azione Index, quindi fare clic con il pulsante destro del mouse e selezionare "Aggiungi visualizzazione". Verrà visualizzata la finestra di dialogo Aggiungi visualizzazione:

Screenshot del menu che mostra la selezione aggiungi visualizzazione.Screenshot della finestra di dialogo Aggiungi visualizzazione, con opzioni di menu per selezionare e aggiungere la visualizzazione.

La finestra di dialogo "Aggiungi visualizzazione" consente di generare rapidamente e facilmente i file di modello di visualizzazione. Per impostazione predefinita, la finestra di dialogo "Aggiungi visualizzazione" precompila il nome del modello Di visualizzazione in modo che corrisponda al metodo di azione che lo userà. Poiché è stato usato il menu di scelta rapida "Aggiungi visualizzazione" all'interno del metodo di azione Index() del nostro HomeController, la finestra di dialogo "Aggiungi visualizzazione" precedente ha "Index" come nome di visualizzazione precompilato per impostazione predefinita. Non è necessario modificare alcuna delle opzioni in questa finestra di dialogo, quindi fare clic sul pulsante Aggiungi.

Quando si fa clic sul pulsante Aggiungi, Visual Web Developer creerà un nuovo modello di visualizzazione Index.cshtml per noi nella directory \Views\Home, creando la cartella se non esiste già.

Screenshot del menu a discesa Esplora soluzioni, che mostra i diversi file nello Store musica M V C.

Il nome e il percorso della cartella del file "Index.cshtml" è importante e segue le convenzioni di denominazione MVC predefinite ASP.NET. Il nome della directory, \Views\Home, corrisponde al controller, denominato HomeController. Il nome del modello di visualizzazione, Index, corrisponde al metodo di azione del controller che visualizzerà la visualizzazione.

ASP.NET MVC consente di evitare di dover specificare in modo esplicito il nome o la posizione di un modello di visualizzazione quando si usa questa convenzione di denominazione per restituire una visualizzazione. Per impostazione predefinita, eseguirà il rendering del modello di visualizzazione \Views\Home\Index.cshtml quando scriviamo codice come indicato di seguito all'interno di HomeController:

public class HomeController : Controller
{
    //
    // GET: /Home/
    public ActionResult Index()
    {
        return View();
    }
}

Visual Web Developer ha creato e aperto il modello di visualizzazione "Index.cshtml" dopo aver fatto clic sul pulsante "Aggiungi" nella finestra di dialogo "Aggiungi visualizzazione". Di seguito è riportato il contenuto di Index.cshtml.

@{
    ViewBag.Title = "Index";
}
<h2>Index</h2>

Questa visualizzazione usa la sintassi Razor, che è più concisa rispetto al motore di visualizzazione Web Forms usato in Web Forms ASP.NET e versioni precedenti di ASP.NET MVC. Il motore di visualizzazione Web Forms è ancora disponibile in ASP.NET MVC 3, ma molti sviluppatori trovano che il motore di visualizzazione Razor si adatta ASP.NET sviluppo MVC davvero bene.

Le prime tre righe impostano il titolo della pagina usando ViewBag.Title. Si esaminerà il funzionamento in modo più dettagliato, ma prima si aggiornerà il testo dell'intestazione di testo e si visualizzerà la pagina. Aggiornare il <tag h2> per dire "Questa è la Home Page" come illustrato di seguito.

@{
    ViewBag.Title = "Index";
}
<h2>This is the Home Page</h2>

L'esecuzione dell'applicazione mostra che il nuovo testo è visibile nella home page.

Screenshot della home page del browser dell'archivio musicale, che mostra il testo

Uso di un layout per gli elementi del sito comuni

La maggior parte dei siti Web ha contenuto condiviso tra molte pagine: navigazione, piè di pagina, immagini di logo, riferimenti a fogli di stile e così via. Il motore di visualizzazione Razor semplifica la gestione tramite una pagina denominata _Layout.cshtml creata automaticamente all'interno della cartella /Views/Shared.

Screenshot del menu a discesa File di Music Store che mostra il percorso del file nella cartella condivisa situata all'interno della cartella di visualizzazione.

Fare doppio clic su questa cartella per visualizzare il contenuto, illustrato di seguito.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")"
rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")"     
            type="text/javascript"></script> 
    <script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")"
            type="text/javascript"></script>
</head>
<body>
    @RenderBody()
</body>
</html>

Il contenuto delle singole visualizzazioni verrà visualizzato dal @RenderBody() comando e qualsiasi contenuto comune che si desidera visualizzare all'esterno di tale oggetto può essere aggiunto al markup _Layout.cshtml. Si vuole che MVC Music Store abbia un'intestazione comune con collegamenti alla home page e all'area Store in tutte le pagine del sito, quindi verrà aggiunto al modello direttamente sopra tale @RenderBody() istruzione.

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")"
rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")"
type="text/javascript"></script>
</head>
<body>
    <div id="header">
        <h1>
            ASP.NET MVC MUSIC STORE</h1>
        <ul id="navlist">
            <li class="first"><a href="/"
id="current">Home</a></li>
            <li><a
href="/Store/">Store</a></li>
        </ul>
    </div>
    @RenderBody()
</body>
</html>

Aggiornamento del foglio di stile

Il modello di progetto vuoto include un file CSS molto semplificato che include solo stili usati per visualizzare i messaggi di convalida. La finestra di progettazione ha fornito alcune immagini e CSS aggiuntive per definire l'aspetto e l'aspetto per il nostro sito, quindi verranno aggiunti ora.

Il file CSS e le immagini aggiornati sono inclusi nella directory Contenuto di MvcMusicStore-Assets.zip disponibile in MVC-Music-Store. Verranno selezionati entrambi in Esplora risorse e li verranno inseriti nella cartella Contenuto della soluzione in Visual Web Developer, come illustrato di seguito:

Screenshot affiancato della directory del contenuto e del menu a discesa di Music Store, che mostra il percorso del file nella cartella immagini nella cartella del contenuto.

Verrà chiesto di confermare se si vuole sovrascrivere il file Site.css esistente. Fare clic su Sì.

Screenshot della casella popup di avviso visualizzata, che richiede di confermare l'azione di sovrascrittura chiedendo se si vuole sostituire il file esistente.

La cartella Contenuto dell'applicazione verrà ora visualizzata come segue:

Screenshot dell'archivio musica, menu a discesa, evidenziando la cartella del contenuto, che mostra la nuova cartella immagine con l'elenco di immagini sottostanti.

Ora eseguiamo l'applicazione e vediamo come vengono visualizzate le modifiche nella home page.

Screenshot della home page del browser dell'archivio musicale, con l'immagine selezionata, insieme alle parole

  • Esaminiamo cosa è cambiato: il metodo di azione Index di HomeController trovato e visualizzato il modello \Views\Home\Index.cshtmlView, anche se il codice denominato "return View()", perché il modello di visualizzazione ha seguito la convenzione di denominazione standard.
  • La Home Page visualizza un semplice messaggio di benvenuto definito all'interno del modello di visualizzazione \Views\Home\Index.cshtml.
  • La Home Page usa il modello _Layout.cshtml e quindi il messaggio di benvenuto è contenuto nel layout HTML del sito standard.

Uso di un modello per passare informazioni alla visualizzazione

Un modello di visualizzazione che visualizza solo il codice HTML hardcoded non farà un sito Web molto interessante. Per creare un sito Web dinamico, si vogliono invece passare informazioni dalle azioni del controller ai modelli di visualizzazione.

Nel modello Model-View-Controller il termine Model fa riferimento a oggetti che rappresentano i dati nell'applicazione. Spesso, gli oggetti modello corrispondono alle tabelle nel database, ma non devono.

I metodi di azione controller che restituiscono un Oggetto ActionResult possono passare un oggetto modello alla vista. In questo modo un controller consente di creare un pacchetto pulito di tutte le informazioni necessarie per generare una risposta e quindi passare queste informazioni a un modello di visualizzazione da usare per generare la risposta HTML appropriata. Questo è più semplice da comprendere visualizzandolo in azione, quindi si inizierà.

Prima di tutto verranno create alcune classi modello per rappresentare generi e album all'interno del nostro archivio. Iniziamo creando una classe Genre. Fare clic con il pulsante destro del mouse sulla cartella "Modelli" all'interno del progetto, scegliere l'opzione "Aggiungi classe" e assegnare un nome al file "Genre.cs".

Screenshot di tre caselle di menu side-by-side, che mostra le indicazioni sul percorso del file, da destra a sinistra, alla selezione della classe

Screenshot delle opzioni di menu aggiungi nuova voce, visualizzando tre menu selezionando un modello, lo stile di ordinamento e il tipo; quindi la barra del campo nome nella parte inferiore.

Aggiungere quindi una proprietà Nome stringa pubblica alla classe creata:

public class Genre
{
    public string Name { get; set; }
}

Nota: se ci si chiede, la notazione { get; set; } usa la funzionalità implementata automaticamente di C#. Ciò ci offre i vantaggi di una proprietà senza richiedere a noi di dichiarare un campo di backing.

Seguire quindi la stessa procedura per creare una classe Album (denominata Album.cs) con una proprietà Title e Genre:

public class Album
{
    public string Title { get; set; }
    public Genre Genre { get; set; }
}

È ora possibile modificare StoreController per usare Visualizzazioni che visualizzano informazioni dinamiche dal modello. Se , a scopo dimostrativo subito, abbiamo denominato i nostri Album in base all'ID richiesta, potremmo visualizzare tali informazioni come nella visualizzazione seguente.

Screenshot della home page nel browser, con il logo dell'immagine, il nome dell'album corrente e i pulsanti home e archiviabili nell'angolo superiore destro.

Si inizierà modificando l'azione Dettagli dello Store in modo da visualizzare le informazioni per un singolo album. Aggiungere un'istruzione "using" all'inizio della classe StoreControllers per includere lo spazio dei nomi MvcMusicStore.Models, quindi non è necessario digitare MvcMusicStore.Models.Album ogni volta che si vuole usare la classe album. La sezione "usings" di tale classe dovrebbe ora essere visualizzata come indicato di seguito.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcMusicStore.Models;

Verrà quindi aggiornata l'azione Controller Details in modo che restituisca un'azione ActionResult anziché una stringa, come si è fatto con il metodo Index di HomeController.

public ActionResult Details(int id)

È ora possibile modificare la logica per restituire un oggetto Album alla visualizzazione. Più avanti in questa esercitazione verranno recuperati i dati da un database, ma per il momento verrà usato "dati fittizi" per iniziare.

public ActionResult Details(int id)
 {
    var album = new Album { Title = "Album " + id };
    return View(album);
 }

Nota: se non si ha familiarità con C#, è possibile presupporre che l'uso di var significa che la variabile dell'album è associata in ritardo. Non è corretto: il compilatore C# usa l'inferenza dei tipi in base a ciò che viene assegnato alla variabile per determinare che l'album è di tipo Album e la compilazione della variabile dell'album locale come tipo album, quindi si ottiene il controllo in fase di compilazione e il supporto dell'editor di codice di Visual Studio.

Verrà ora creato un modello di visualizzazione che usa l'album per generare una risposta HTML. Prima di eseguire questa operazione, è necessario compilare il progetto in modo che la finestra di dialogo Aggiungi visualizzazione sappia la classe Album appena creata. È possibile compilare il progetto selezionando la voce di menu Debug⇨Build MvcMusicStore (per un credito aggiuntivo, è possibile usare il collegamento CTRL-MAIUSC-B per compilare il progetto).

Screenshot dell'editor di documenti dell'archivio musicale, con la scheda

Dopo aver configurato le classi di supporto, è possibile compilare il modello Di visualizzazione. Fare clic con il pulsante destro del mouse sul metodo Details e selezionare "Aggiungi visualizzazione..." dal menu di scelta rapida.

Screenshot del menu modello di visualizzazione, visualizzazione su un frammento di codice e evidenziazione dell'opzione

Si creerà un nuovo modello di visualizzazione come fatto prima con HomeController. Poiché la creazione viene creata da StoreController, verrà generata per impostazione predefinita in un file \Views\Store\Index.cshtml.

A differenza di prima, verrà selezionata la casella di controllo "Crea una visualizzazione fortemente tipizzata". Verrà quindi selezionata la classe "Album" all'interno dell'elenco a discesa "Visualizza classe dati". In questo modo la finestra di dialogo "Aggiungi visualizzazione" crea un modello di visualizzazione che prevede che un oggetto Album venga passato a esso.

Screenshot della finestra del menu aggiungi visualizzazione, che mostra la casella di controllo

Quando si fa clic sul pulsante "Aggiungi" verrà creato il modello \Views\Store\Details.cshtml View, contenente il codice seguente.

@model MvcMusicStore.Models.Album
@{
    ViewBag.Title = "Details";
}
<h2>Details</h2>

Si noti la prima riga, che indica che questa visualizzazione è fortemente tipizzata nella classe Album. Il motore di visualizzazione Razor riconosce che è stato passato un oggetto Album, in modo da poter accedere facilmente alle proprietà del modello e anche avere il vantaggio di IntelliSense nell'editor per sviluppatori Visual Web.

Aggiornare il tag h2> in modo che visualizzi la <proprietà Title dell'album modificando la riga da visualizzare come indicato di seguito.

<h2>Album: @Model.Title</h2>

Si noti che IntelliSense viene attivato quando si immette il periodo dopo la @Model parola chiave, che mostra le proprietà e i metodi supportati dalla classe Album.

Ora eseguiamo nuovamente il progetto e visita l'URL /Store/Details/5. Verranno visualizzati i dettagli di un album come riportato di seguito.

Screenshot della finestra del browser della home page, con il logo dell'immagine nella parte superiore sinistra e il nome dell'album sotto di esso.

A questo punto si eseguirà un aggiornamento simile per il metodo di azione Sfoglia dello Store. Aggiornare il metodo in modo che restituisca un ActionResult e modificare la logica del metodo in modo che crei un nuovo oggetto Genre e lo restituisca alla vista.

public ActionResult Browse(string genre)
 {
    var genreModel = new Genre { Name = genre };
    return View(genreModel);
 }

Fare clic con il pulsante destro del mouse sul metodo Sfoglia e scegliere "Aggiungi visualizzazione..." dal menu di scelta rapida, quindi aggiungere una visualizzazione fortemente tipizzata aggiungere un tipo fortemente digitato alla classe Genre.

Screenshot del menu di scelta rapida, che mostra l'opzione

Aggiornare l'elemento <h2> nel codice di visualizzazione (in /Views/Store/Browse.cshtml) per visualizzare le informazioni sul genere.

@model MvcMusicStore.Models.Genre
@{
    ViewBag.Title = "Browse";
}
<h2>Browsing Genre: @Model.Name</h2>

Eseguire nuovamente il progetto e passare a /Store/Sfoglia? Genere=URL disco. Verrà visualizzata la pagina Sfoglia come illustrato di seguito.

Screenshot della home page del browser, che visualizza il messaggio

Infine, è possibile eseguire un aggiornamento leggermente più complesso al metodo di azione dell'indice dello Store e visualizzare un elenco di tutti i generi nel nostro negozio. Verrà eseguita questa operazione usando un elenco di generi come oggetto modello, anziché solo un singolo genere.

public ActionResult Index()
{
    var genres = new List<Genre>
    {
        new Genre { Name = "Disco"},
        new Genre { Name = "Jazz"},
        new Genre { Name = "Rock"}
    };
    return View(genres);
 }

Fare clic con il pulsante destro del mouse sul metodo di azione Store Index e selezionare Aggiungi visualizzazione come prima, selezionare Genere come classe Modello e premere il pulsante Aggiungi.

Screenshot del menu della finestra

Prima di tutto, verrà modificata la @model dichiarazione in modo da indicare che la visualizzazione prevede diversi oggetti Genere anziché uno solo. Modificare la prima riga di /Store/Index.cshtml per leggere come indicato di seguito:

@model IEnumerable<MvcMusicStore.Models.Genre>

Questo indica al motore di visualizzazione Razor che funzionerà con un oggetto modello che può contenere diversi oggetti Genere. Si usa un genere IEnumerable<> anziché un genere elenco<> perché è più generico, consentendoci di modificare il tipo di modello in un secondo momento in qualsiasi tipo di oggetto che supporti l'interfaccia IEnumerable.

Verrà quindi eseguito il ciclo degli oggetti Genere nel modello, come illustrato nel codice di visualizzazione completato riportato di seguito.

@model IEnumerable<MvcMusicStore.Models.Genre>
@{
    ViewBag.Title = "Store";
}
<h3>Browse Genres</h3>
<p>
    Select from @Model.Count()
genres:</p>
<ul>
    @foreach (var genre in Model)
    {
        <li>@genre.Name</li>
    }
</ul>

Si noti che è disponibile il supporto completo di IntelliSense durante l'immissione di questo codice, in modo che quando si digita "@Model". Vengono visualizzati tutti i metodi e le proprietà supportate da un oggetto IEnumerable di tipo Genere.

Screenshot del frammento di codice H T M L, con una barra dei menu su di esso, selezionando il comando 'count <>'.

All'interno del ciclo "foreach", Visual Web Developer sa che ogni elemento è di tipo Genere, quindi viene visualizzato IntelliSense per ogni tipo di genere.

Screenshot del codice

Successivamente, la funzionalità di scaffolding ha esaminato l'oggetto Genre e ha determinato che ognuno avrà una proprietà Name, in modo da scorrere e scriverli in uscita. Genera anche collegamenti Modifica, Dettagli ed Elimina a ogni singolo elemento. In un secondo momento, nel nostro responsabile dello store, ma per il momento vorremmo avere un elenco semplice.

Quando si esegue l'applicazione e si passa a /Store, viene visualizzato sia il conteggio che l'elenco di generi.

Screenshot della finestra del browser, che mostra il titolo

L'URL /Store che elenca attualmente i generi elenca i nomi di genere semplicemente come testo normale. Cambiamo questo in modo che invece di testo normale abbiamo invece il collegamento Nomi di genere all'URL /Store/Sfoglia appropriato, in modo che facendo clic su un genere musicale come "Disco" passerà all'URL /Store/Sfoglia?genere=Disco. È possibile aggiornare il modello di visualizzazione \Views\Store\Index.cshtml per restituire questi collegamenti usando il codice come riportato di seguito (non digitare questo oggetto in - verrà migliorato in questo modo):

<ul>
    @foreach (var genre in Model)
    {
        <li><a href="/Store/Browse?genre=@genre.Name">@genre.Name</a></li>
    }
</ul>

Ciò funziona, ma potrebbe causare problemi in un secondo momento perché si basa su una stringa hardcoded. Ad esempio, se si vuole rinominare il controller, è necessario cercare i collegamenti che devono essere aggiornati.

Un approccio alternativo che è possibile usare consiste nel sfruttare un metodo helper HTML. ASP.NET MVC include metodi helper HTML disponibili nel codice modello di visualizzazione per eseguire diverse attività comuni come questa. Il metodo helper Html.ActionLink() è uno particolarmente utile e semplifica la compilazione di collegamenti HTML <> e si occupa di dettagli fastidiosi, ad esempio assicurarsi che i percorsi URL siano codificati correttamente.

Html.ActionLink() include diversi overload per consentire di specificare la quantità di informazioni necessarie per i collegamenti. Nel caso più semplice, si fornirà solo il testo del collegamento e il metodo Action da passare a quando il collegamento ipertestuale viene fatto clic sul client. Ad esempio, è possibile collegare il metodo "/Store/" Index() nella pagina Dettagli dello Store con il testo del collegamento "Vai all'indice dello Store" usando la chiamata seguente:

@Html.ActionLink("Go
to the Store Index", "Index")

Nota: in questo caso, non è necessario specificare il nome del controller perché si sta semplicemente collegando a un'altra azione all'interno dello stesso controller che esegue il rendering della visualizzazione corrente.

I collegamenti alla pagina Sfoglia dovranno tuttavia passare un parametro, quindi verrà usato un altro overload del metodo Html.ActionLink che accetta tre parametri:

    1. Testo del collegamento, che visualizzerà il nome Genere
    1. Nome azione controller (Sfoglia)
    1. Valori dei parametri di route, specificando sia il nome (Genere) che il valore (Nome genere)

Mettere insieme tutto questo, ecco come scriveremo questi collegamenti alla visualizzazione Indice dello Store:

<ul>
    @foreach (var genre in Model)
    {
        <li>@Html.ActionLink(genre.Name,
"Browse", new { genre = genre.Name })</li>
    }
</ul>

Ora quando si esegue di nuovo il progetto e si accede all'URL /Store/ verrà visualizzato un elenco di generi. Ogni genere è un collegamento ipertestuale: quando viene fatto clic, verrà visualizzato l'URL /Store/Browse?genre=[genere].

Screenshot della finestra del browser, che mostra il titolo Sfoglia genere, con il messaggio'select da 3 generi' seguito da tre selezioni di genere puntate.

Il codice HTML per l'elenco di generi è simile al seguente:

<ul>
    <li><a href="/Store/Browse?genre=Disco">Disco</a>
</li>
    <li><a href="/Store/Browse?genre=Jazz">Jazz</a>
</li>
    <li><a href="/Store/Browse?genre=Rock">Rock</a>
</li>
</ul>