Usare controller e visualizzazioni per implementare un'interfaccia utente elenco/dettagli
di Microsoft
Questo è il passaggio 4 di un'esercitazione gratuita sull'applicazione "NerdDinner" che illustra come creare un'applicazione Web di piccole dimensioni, ma completa, usando ASP.NET MVC 1.
Il passaggio 4 illustra come aggiungere un controller all'applicazione che sfrutta il modello per offrire agli utenti un'esperienza di navigazione di presentazione/dettagli dei dati per le cene nel sito NerdDinner.
Se si usa ASP.NET MVC 3, è consigliabile seguire le esercitazioni Introduzione Con MVC 3 o MVC Music Store.
NerdDinner Passaggio 4: Controller e visualizzazioni
Con i framework Web tradizionali (ASP classico, PHP, Web Forms ASP.NET e così via), gli URL in ingresso vengono in genere mappati ai file su disco. Ad esempio, una richiesta per un URL come "/Products.aspx" o "/Products.php" potrebbe essere elaborata da un file "Products.aspx" o "Products.php".
I framework MVC basati sul Web eseguono il mapping degli URL al codice del server in modo leggermente diverso. Anziché eseguire il mapping degli URL in ingresso ai file, esegue invece il mapping degli URL ai metodi nelle classi. Queste classi sono denominate "Controller" e sono responsabili dell'elaborazione delle richieste HTTP in ingresso, della gestione dell'input dell'utente, del recupero e del salvataggio dei dati e della determinazione della risposta da inviare al client (visualizzare HTML, scaricare un file, reindirizzare a un URL diverso e così via).
Ora che è stato creato un modello di base per l'applicazione NerdDinner, il passaggio successivo consiste nell'aggiungere un controller all'applicazione che ne trae vantaggio per fornire agli utenti un'esperienza di navigazione di presentazione/dettagli dei dati per Le cene nel nostro sito.
Aggiunta di un controller DinnersController
Si inizierà facendo clic con il pulsante destro del mouse sulla cartella "Controller" all'interno del progetto Web e quindi selezionando il comando di menu Aggiungi> controller (è anche possibile eseguire questo comando digitando CTRL-M, CTRL-C):
Verrà visualizzata la finestra di dialogo "Aggiungi controller":
Il nuovo controller sarà "DinnersController" e fare clic sul pulsante "Aggiungi". Visual Studio aggiungerà quindi un file DinnersController.cs nella directory \Controllers:
Verrà aperta anche la nuova classe DinnersController all'interno dell'editor di codice.
Aggiunta di metodi di azione Index() e Details() alla classe DinnersController
Si vuole consentire ai visitatori di usare l'applicazione per visualizzare un elenco di cene imminenti e consentire loro di fare clic su qualsiasi cena nell'elenco per visualizzare dettagli specifici su di esso. Questa operazione verrà eseguita pubblicando gli URL seguenti dall'applicazione:
URL | Scopo |
---|---|
/Cene/ | Visualizzare un elenco HTML delle prossime cene |
/Dinners/Details/[id] | Visualizzare i dettagli relativi a una cena specifica indicata da un parametro "id" incorporato nell'URL, che corrisponderà all'ID Cena della cena nel database. Ad esempio: /Dinners/Details/2 visualizzerebbe una pagina HTML con i dettagli sulla cena il cui valore DinnerID è 2. |
Verranno pubblicate le implementazioni iniziali di questi URL aggiungendo due "metodi di azione" pubblici alla classe DinnersController, come illustrato di seguito:
public class DinnersController : Controller {
//
// HTTP-GET: /Dinners/
public void Index() {
Response.Write("<h1>Coming Soon: Dinners</h1>");
}
//
// HTTP-GET: /Dinners/Details/2
public void Details(int id) {
Response.Write("<h1>Details DinnerID: " + id + "</h1>");
}
}
Si eseguirà quindi l'applicazione NerdDinner e si userà il browser per richiamarli. La digitazione nell'URL "/Dinners/" causerà l'esecuzione del metodo Index() e restituirà la risposta seguente:
Se si digita l'URL "/Dinners/Details/2", il metodo Details() verrà eseguito e verrà restituita la risposta seguente:
Ci si potrebbe chiedere : in che modo ASP.NET MVC sa creare la classe DinnersController e richiamare tali metodi? Per comprendere il funzionamento del routing, è necessario esaminare rapidamente il funzionamento del routing.
Informazioni sul routing MVC ASP.NET
ASP.NET MVC include un potente motore di routing degli URL che offre una notevole flessibilità nel controllo del mapping degli URL alle classi controller. Consente di personalizzare completamente il modo in cui ASP.NET MVC sceglie la classe controller da creare, quale metodo richiamare su di esso, nonché configurare diversi modi in cui le variabili possono essere analizzate automaticamente dall'URL/Querystring e passate al metodo come argomenti di parametro. Offre la flessibilità necessaria per ottimizzare completamente un sito per SEO (ottimizzazione del motore di ricerca) e pubblicare qualsiasi struttura di URL desiderata da un'applicazione.
Per impostazione predefinita, i nuovi progetti MVC ASP.NET sono dotati di un set preconfigurato di regole di routing URL già registrate. In questo modo è possibile iniziare facilmente a usare un'applicazione senza dover configurare in modo esplicito alcun elemento. Le registrazioni predefinite delle regole di routing sono disponibili nella classe "Application" dei progetti, che è possibile aprire facendo doppio clic sul file "Global.asax" nella radice del progetto:
Le regole di routing MVC predefinite ASP.NET vengono registrate nel metodo "RegisterRoutes" di questa classe:
public void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL w/ params
new { controller="Home", action="Index",id="" } // Param defaults
);
}
Le "route. La chiamata al metodo MapRoute()" precedente registra una regola di routing predefinita che esegue il mapping degli URL in ingresso alle classi controller usando il formato URL: "/{controller}/{action}/{id}", dove "controller" è il nome della classe controller per creare un'istanza, "action" è il nome di un metodo pubblico da richiamare su di esso e "id" è un parametro facoltativo incorporato all'interno dell'URL che può essere passato come argomento al metodo. Il terzo parametro passato alla chiamata al metodo "MapRoute()" è un set di valori predefiniti da usare per i valori controller/action/id nel caso in cui non siano presenti nell'URL (Controller = "Home", Action="Index", Id="").
Di seguito è riportata una tabella che illustra come viene eseguito il mapping di un'ampia gamma di URL usando la regola di route predefinita "/{controllers}/{action}/{id}":
URL | Classe controller | Metodo Azione | Parametri passati |
---|---|---|---|
/Dinners/Details/2 | DinnersController | Details(id) | id=2 |
/Dinners/Edit/5 | DinnersController | Edit(id) | id=5 |
/Dinners/Create | DinnersController | Create() | N/D |
/Cene | DinnersController | Index() | N/D |
/Casa | Homecontroller | Index() | N/D |
/ | Homecontroller | Index() | N/D |
Le ultime tre righe mostrano i valori predefiniti (Controller = Home, Action = Index, Id = "") usati. Poiché il metodo "Index" viene registrato come nome di azione predefinito se non ne viene specificato uno, gli URL "/Dinners" e "/Home" fanno sì che il metodo di azione Index() venga richiamato nelle relative classi controller. Poiché il controller "Home" viene registrato come controller predefinito se non ne viene specificato uno, l'URL "/" fa sì che venga creato HomeController e che venga richiamato il metodo di azione Index().
Se non si preferisce queste regole di routing degli URL predefinite, la buona notizia è che sono facili da modificare. È sufficiente modificarle all'interno del metodo RegisterRoutes precedente. Per l'applicazione NerdDinner, tuttavia, non verranno modificate le regole di routing degli URL predefinite, ma verranno usate così com'è.
Uso di DinnerRepository dal nostro DinnersController
Sostituire ora l'implementazione corrente dei metodi di azione Index() e Details() di DinnersController con implementazioni che usano il modello.
Verrà usata la classe DinnerRepository creata in precedenza per implementare il comportamento. Si inizierà aggiungendo un'istruzione "using" che fa riferimento allo spazio dei nomi "NerdDinner.Models" e quindi dichiarando un'istanza di DinnerRepository come campo nella classe DinnerController.
Più avanti in questo capitolo verrà presentato il concetto di "Inserimento delle dipendenze" e verrà illustrato un altro modo per consentire ai controller di ottenere un riferimento a un oggetto DinnerRepository che consente un test unità migliore, ma per il momento si creerà solo un'istanza dell'inline DinnerRepository come illustrato di seguito.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using NerdDinner.Models;
namespace NerdDinner.Controllers {
public class DinnersController : Controller {
DinnerRepository dinnerRepository = new DinnerRepository();
//
// GET: /Dinners/
public void Index() {
var dinners = dinnerRepository.FindUpcomingDinners().ToList();
}
//
// GET: /Dinners/Details/2
public void Details(int id) {
Dinner dinner = dinnerRepository.GetDinner(id);
}
}
}
A questo momento è possibile generare una risposta HTML usando gli oggetti del modello di dati recuperati.
Uso delle visualizzazioni con il controller
Anche se è possibile scrivere codice all'interno dei metodi di azione per assemblare HTML e quindi usare il metodo helper Response.Write() per inviarlo al client, questo approccio diventa piuttosto difficile rapidamente. Un approccio molto migliore consiste nell'eseguire solo l'applicazione e la logica dei dati all'interno dei metodi di azione DinnersController e quindi passare i dati necessari per eseguire il rendering di una risposta HTML a un modello di "visualizzazione" separato responsabile dell'output della relativa rappresentazione HTML. Come vedremo in un momento, un modello di "visualizzazione" è un file di testo che in genere contiene una combinazione di markup HTML e codice di rendering incorporato.
La separazione della logica del controller dal rendering della visualizzazione offre numerosi vantaggi. In particolare, consente di applicare una chiara "separazione delle preoccupazioni" tra il codice dell'applicazione e la formattazione/rendering dell'interfaccia utente. In questo modo è molto più semplice eseguire unit test della logica dell'applicazione in isolamento dalla logica di rendering dell'interfaccia utente. Semplifica la modifica dei modelli di rendering dell'interfaccia utente senza dover apportare modifiche al codice dell'applicazione. E può semplificare la collaborazione tra sviluppatori e progettisti sui progetti.
È possibile aggiornare la classe DinnersController per indicare che si vuole usare un modello di visualizzazione per inviare una risposta dell'interfaccia utente HTML modificando le firme del metodo dei due metodi di azione, dalla presenza di un tipo restituito "void" al tipo restituito "ActionResult". È quindi possibile chiamare il metodo helper View() nella classe base Controller per restituire un oggetto "ViewResult" simile al seguente:
public class DinnersController : Controller {
DinnerRepository dinnerRepository = new DinnerRepository();
//
// GET: /Dinners/
public ActionResult Index() {
var dinners = dinnerRepository.FindUpcomingDinners().ToList();
return View("Index", dinners);
}
//
// GET: /Dinners/Details/2
public ActionResult Details(int id) {
Dinner dinner = dinnerRepository.GetDinner(id);
if (dinner == null)
return View("NotFound");
else
return View("Details", dinner);
}
}
La firma del metodo helper View() in uso sopra è simile alla seguente:
Il primo parametro del metodo helper View() è il nome del file modello di visualizzazione che si vuole usare per eseguire il rendering della risposta HTML. Il secondo parametro è un oggetto modello che contiene i dati necessari al modello di visualizzazione per eseguire il rendering della risposta HTML.
All'interno del metodo di azione Index() viene chiamato il metodo helper View() e viene indicato che si vuole eseguire il rendering di un elenco HTML delle cene usando un modello di visualizzazione "Index". Il modello di visualizzazione viene passato a una sequenza di oggetti Dinner da cui generare l'elenco:
//
// GET: /Dinners/
public ActionResult Index() {
var dinners = dinnerRepository.FindUpcomingDinners().ToList();
return View("Index", dinners);
}
All'interno del metodo di azione Details() si tenta di recuperare un oggetto Dinner usando l'ID fornito all'interno dell'URL. Se viene trovata una cena valida, viene chiamato il metodo helper View(), che indica che si vuole usare un modello di visualizzazione "Dettagli" per eseguire il rendering dell'oggetto Dinner recuperato. Se viene richiesta una cena non valida, viene visualizzato un messaggio di errore utile che indica che dinner non esiste usando un modello di visualizzazione "NotFound" (e una versione di overload del metodo helper View() che accetta solo il nome del modello:
//
// GET: /Dinners/Details/2
public ActionResult Details(int id) {
Dinner dinner = dinnerRepository.FindDinner(id);
if (dinner == null)
return View("NotFound");
else
return View("Details", dinner);
}
Verranno ora implementati i modelli di visualizzazione "NotFound", "Details" e "Index".
Implementazione del modello di visualizzazione "NotFound"
Si inizierà implementando il modello di visualizzazione "NotFound", che visualizza un messaggio di errore descrittivo che indica che non è possibile trovare la cena richiesta.
Verrà creato un nuovo modello di visualizzazione posizionando il cursore di testo all'interno di un metodo di azione del controller, quindi fare clic con il pulsante destro del mouse e scegliere il comando di menu "Aggiungi visualizzazione" (è anche possibile eseguire questo comando digitando CTRL-M, CTRL-V):
Verrà visualizzata una finestra di dialogo "Aggiungi visualizzazione" come illustrato di seguito. Per impostazione predefinita, la finestra di dialogo prepopocherà il nome della visualizzazione per creare in modo che corrisponda al nome del metodo di azione in cui si trovava il cursore al momento dell'avvio della finestra di dialogo (in questo caso "Dettagli"). Poiché si vuole prima implementare il modello "NotFound", si eseguirà l'override di questo nome di visualizzazione e verrà impostato su "NotFound":
Quando si fa clic sul pulsante "Aggiungi", Visual Studio creerà un nuovo modello di visualizzazione "NotFound.aspx" all'interno della directory "\Views\Dinners", che verrà creata anche se la directory non esiste già:
Verrà aperto anche il nuovo modello di visualizzazione "NotFound.aspx" all'interno dell'editor di codice:
Per impostazione predefinita, i modelli di visualizzazione hanno due "aree di contenuto" in cui è possibile aggiungere contenuto e codice. Il primo consente di personalizzare il "titolo" della pagina HTML restituita. Il secondo consente di personalizzare il "contenuto principale" della pagina HTML inviata di nuovo.
Per implementare il modello di visualizzazione "NotFound" aggiungeremo alcuni contenuti di base:
<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
Dinner Not Found
</asp:Content>
<asp:Content ID="Main" ContentPlaceHolderID="MainContent" runat="server">
<h2>Dinner Not Found</h2>
<p>Sorry - but the dinner you requested doesn't exist or was deleted.</p>
</asp:Content>
È quindi possibile provarlo all'interno del browser. A tale scopo, richiedere l'URL "/Dinners/Details/9999". Questo farà riferimento a una cena che non esiste attualmente nel database e causerà il rendering del modello di visualizzazione "NotFound" del metodo di azione DinnersController.Details():
Una cosa che noterai nella schermata precedente è che il modello di visualizzazione di base ha ereditato un gruppo di HTML che circonda il contenuto principale sullo schermo. Questo perché il modello di visualizzazione usa un modello di "pagina master" che consente di applicare un layout coerente in tutte le visualizzazioni del sito. Verrà illustrato come funzionano più avanti le pagine master in una parte successiva di questa esercitazione.
Implementazione del modello di visualizzazione "Dettagli"
Verrà ora implementato il modello di visualizzazione "Dettagli", che genererà il codice HTML per un singolo modello Dinner.
A tale scopo, posizionare il cursore di testo all'interno del metodo di azione Dettagli, quindi fare clic con il pulsante destro del mouse e scegliere il comando di menu "Aggiungi visualizzazione" (o premere CTRL-M, CTRL-V):
Verrà visualizzata la finestra di dialogo "Aggiungi visualizzazione". Il nome di visualizzazione predefinito ("Dettagli") verrà mantenuto. Selezionare anche la casella di controllo "Crea una visualizzazione fortemente tipizzata" nella finestra di dialogo e selezionare (usando l'elenco a discesa casella combinata) il nome del tipo di modello passato dal controller alla visualizzazione. Per questa visualizzazione viene passato un oggetto Dinner (il nome completo per questo tipo è: "NerdDinner.Models.Dinner"):
A differenza del modello precedente, in cui si è scelto di creare una "Visualizzazione vuota", questa volta si sceglie di "eseguire automaticamente lo scaffolding" della visualizzazione usando un modello "Dettagli". È possibile indicare questo valore modificando l'elenco a discesa "Visualizza contenuto" nella finestra di dialogo precedente.
"Scaffolding" genererà un'implementazione iniziale del modello di visualizzazione dei dettagli in base all'oggetto Dinner che viene passato. In questo modo è possibile iniziare rapidamente a usare l'implementazione del modello di visualizzazione.
Quando si fa clic sul pulsante "Aggiungi", Visual Studio creerà un nuovo file modello di visualizzazione "Details.aspx" all'interno della directory "\Views\Dinners":
Verrà anche aperto il nuovo modello di visualizzazione "Details.aspx" all'interno dell'editor di codice. Conterrà un'implementazione iniziale dello scaffolding di una visualizzazione dei dettagli basata su un modello Dinner. Il motore di scaffolding usa la reflection .NET per esaminare le proprietà pubbliche esposte sulla classe passata e aggiungerà contenuto appropriato in base a ogni tipo trovato:
<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
Details
</asp:Content>
<asp:Content ID="Main" ContentPlaceHolderID="MainContent" runat="server">
<h2>Details</h2>
<fieldset>
<legend>Fields</legend>
<p>
DinnerID:
<%=Html.Encode(Model.DinnerID) %>
</p>
<p>
Title:
<%=Html.Encode(Model.Title) %>
</p>
<p>
EventDate:
<%= Html.Encode(String.Format("{0:g}", Model.EventDate)) %>
</p>
<p>
Description:
<%=Html.Encode(Model.Description) %>
</p>
<p>
HostedBy:
<%=Html.Encode(Model.HostedBy) %>
</p>
<p>
ContactPhone:
<%=Html.Encode(Model.ContactPhone) %>
</p>
<p>
Address:
<%=Html.Encode(Model.Address) %>
</p>
<p>
Country:
<%=Html.Encode(Model.Country) %>
</p>
<p>
Latitude:
<%= Html.Encode(String.Format("{0:F}",Model.Latitude)) %>
</p>
<p>
Longitude:
<%= Html.Encode(String.Format("{0:F}",Model.Longitude)) %>
</p>
</fieldset>
<p>
<%=Html.ActionLink("Edit","Edit", new { id=Model.DinnerID }) %>|
<%=Html.ActionLink("Back to List", "Index") %>
</p>
</asp:Content>
È possibile richiedere l'URL "/Dinners/Details/1" per visualizzare l'aspetto dell'implementazione dello scaffold "details" nel browser. Con questo URL verrà visualizzata una delle cene aggiunte manualmente al database al momento della creazione:
In questo modo è possibile eseguire rapidamente e offre un'implementazione iniziale della visualizzazione Details.aspx. È quindi possibile modificarla per personalizzare l'interfaccia utente in base alla soddisfazione.
Quando si esamina più attentamente il modello Details.aspx, si scoprirà che contiene codice HTML statico e codice di rendering incorporato. <% %> code nuggets execute code when the view template renders, and <%= %> code nuggets execute the code contained them and then render the result to the output stream of the template.
È possibile scrivere codice all'interno della visualizzazione che accede all'oggetto modello "Dinner" passato dal controller usando una proprietà "Model" fortemente tipizzata. Visual Studio offre codice intelliSense completo quando si accede a questa proprietà "Model" all'interno dell'editor:
Verranno ora apportate alcune modifiche in modo che l'origine per il modello di visualizzazione Dettagli finale sia simile alla seguente:
<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
Dinner: <%=Html.Encode(Model.Title) %>
</asp:Content>
<asp:Content ID="Main" ContentPlaceHolderID="MainContent" runat="server">
<h2><%=Html.Encode(Model.Title) %></h2>
<p>
<strong>When:</strong>
<%=Model.EventDate.ToShortDateString() %>
<strong>@</strong>
<%=Model.EventDate.ToShortTimeString() %>
</p>
<p>
<strong>Where:</strong>
<%=Html.Encode(Model.Address) %>,
<%=Html.Encode(Model.Country) %>
</p>
<p>
<strong>Description:</strong>
<%=Html.Encode(Model.Description) %>
</p>
<p>
<strong>Organizer:</strong>
<%=Html.Encode(Model.HostedBy) %>
(<%=Html.Encode(Model.ContactPhone) %>)
</p>
<%= Html.ActionLink("Edit Dinner", "Edit", new { id=Model.DinnerID })%> |
<%= Html.ActionLink("Delete Dinner","Delete", new { id=Model.DinnerID})%>
</asp:Content>
Quando si accede nuovamente all'URL "/Dinners/Details/1", il rendering sarà simile al seguente:
Implementazione del modello di visualizzazione "Index"
A questo punto si implementa il modello di visualizzazione "Indice", che genererà un elenco delle prossime cene. A tale scopo, il cursore di testo verrà posizionato all'interno del metodo di azione Indice, quindi fare clic con il pulsante destro del mouse e scegliere il comando di menu "Aggiungi visualizzazione" (oppure premere CTRL-M, CTRL-V).
Nella finestra di dialogo "Aggiungi visualizzazione" si manterrà il modello di visualizzazione denominato "Index" e si seleziona la casella di controllo "Crea una visualizzazione fortemente tipizzata". Questa volta si sceglie di generare automaticamente un modello di visualizzazione "Elenco" e selezionare "NerdDinner.Models.Dinner" come tipo di modello passato alla visualizzazione (che perché è stato indicato che si sta creando uno scaffolding "Elenco" causerà il passaggio di una sequenza di oggetti Dinner dal controller alla visualizzazione):
Quando si fa clic sul pulsante "Aggiungi", Visual Studio creerà un nuovo file modello di visualizzazione "Index.aspx" all'interno della directory "\Views\Dinners". Verrà "scaffolding" un'implementazione iniziale all'interno di essa che fornisce un elenco di tabelle HTML delle cene passate alla visualizzazione.
Quando si esegue l'applicazione e si accede all'URL "/Dinners/" verrà eseguito il rendering dell'elenco delle cene in questo modo:
La soluzione di tabella precedente offre un layout simile alla griglia dei dati dinner, che non è proprio quello che vogliamo per il nostro consumer che si trova a cena. È possibile aggiornare il modello di visualizzazione Index.aspx e modificarlo per elencare meno colonne di dati e usare un <elemento ul> per eseguirne il rendering anziché una tabella usando il codice seguente:
<asp:Content ID="Main" ContentPlaceHolderID="MainContent" runat="server">
<h2>Upcoming Dinners</h2>
<ul>
<% foreach (var dinner in Model) { %>
<li>
<%=Html.Encode(dinner.Title) %>
on
<%=Html.Encode(dinner.EventDate.ToShortDateString())%>
@
<%=Html.Encode(dinner.EventDate.ToShortTimeString())%>
</li>
<% } %>
</ul>
</asp:Content>
Viene usata la parola chiave "var" all'interno dell'istruzione foreach precedente durante il ciclo di ogni cena nel modello. Coloro che non hanno familiarità con C# 3.0 potrebbero pensare che l'uso di "var" significa che l'oggetto dinner è associato in ritardo. Significa invece che il compilatore usa l'inferenza del tipo rispetto alla proprietà "Model" fortemente tipizzata (che è di tipo "IEnumerable<Dinner>") e compila la variabile "dinner" locale come tipo Dinner, ovvero si ottiene il controllo completo intellisense e il controllo in fase di compilazione per esso all'interno di blocchi di codice:
Quando si raggiunge l'aggiornamento nell'URL /Dinners nel browser, la visualizzazione aggiornata è ora simile alla seguente:
Questo aspetto è migliore, ma non è ancora completamente lì. L'ultimo passaggio consiste nell'consentire agli utenti finali di fare clic su singole cene nell'elenco e visualizzare i dettagli su di essi. Questa operazione verrà implementata eseguendo il rendering degli elementi del collegamento ipertestuale HTML che si collegano al metodo di azione Details sul nostro DinnersController.
È possibile generare questi collegamenti ipertestuali all'interno della visualizzazione Indice in uno dei due modi seguenti. Il primo consiste nel creare manualmente un elemento HTML <come quello riportato di seguito, in cui vengono incorporati <%> blocchi all'interno di <un> elemento HTML:>
Un approccio alternativo che è possibile usare consiste nel sfruttare il metodo helper "Html.ActionLink()" predefinito all'interno di ASP.NET MVC che supporta la creazione a livello di codice di un> elemento HTML <che collega a un altro metodo di azione in un controller:
<%= Html.ActionLink(dinner.Title, "Details", new { id=dinner.DinnerID }) %>
Il primo parametro del metodo helper Html.ActionLink() è il testo del collegamento da visualizzare (in questo caso il titolo della cena), il secondo parametro è il nome dell'azione controller a cui si vuole generare il collegamento (in questo caso il metodo Details) e il terzo parametro è un set di parametri da inviare all'azione (implementato come tipo anonimo con nome/valori di proprietà). In questo caso si specifica il parametro "id" della cena a cui si vuole eseguire il collegamento e poiché la regola di routing dell'URL predefinita in ASP.NET MVC è "{Controller}/{Action}/{id}" il metodo helper Html.ActionLink() genererà l'output seguente:
<a href="/Dinners/Details/1">.NET Futures</a>
Per la visualizzazione Index.aspx si userà l'approccio helper Html.ActionLink() e si otterrà ogni cena nel collegamento all'URL dei dettagli appropriato:
<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
Upcoming Dinners
</asp:Content>
<asp:Content ID="Main" ContentPlaceHolderID="MainContent" runat="server">
<h2>Upcoming Dinners</h2>
<ul>
<% foreach (var dinner in Model) { %>
<li>
<%=Html.ActionLink(dinner.Title, "Details", new { id=dinner.DinnerID }) %>
on
<%=Html.Encode(dinner.EventDate.ToShortDateString())%>
@
<%=Html.Encode(dinner.EventDate.ToShortTimeString())%>
</li>
<% } %>
</ul>
</asp:Content>
E ora quando si raggiunge l'URL /Dinners l'elenco delle cene è simile al seguente:
Quando si fa clic su una delle cene nell'elenco, si passerà per visualizzare i dettagli su di esso:
Denominazione basata su convenzioni e struttura di directory \Views
ASP.NET applicazioni MVC per impostazione predefinita usano una struttura di denominazione di directory basata su convenzioni durante la risoluzione dei modelli di visualizzazione. Ciò consente agli sviluppatori di evitare di dover qualificare completamente un percorso di posizione quando si fa riferimento alle visualizzazioni dall'interno di una classe Controller. Per impostazione predefinita, ASP.NET MVC cercherà il file del modello di visualizzazione all'interno della directory *\Views[ControllerName]* sotto l'applicazione.
Ad esempio, stiamo lavorando alla classe DinnersController, che fa riferimento in modo esplicito a tre modelli di visualizzazione: "Index", "Details" e "NotFound". ASP.NET MVC cercherà per impostazione predefinita queste visualizzazioni all'interno della directory \Views\Dinners sotto la directory radice dell'applicazione:
Si noti che attualmente sono presenti tre classi controller all'interno del progetto (DinnersController, HomeController e AccountController, le ultime due sono state aggiunte per impostazione predefinita al momento della creazione del progetto) e sono presenti tre sottodirectory (una per ogni controller) all'interno della directory \Views.
Le visualizzazioni a cui si fa riferimento dai controller Home e Accounts risolveranno automaticamente i modelli di visualizzazione dalle rispettive directory \Views\Home e \Views\Account . La sottodirectory \Views\Shared consente di archiviare i modelli di visualizzazione che vengono riutilizzati tra più controller all'interno dell'applicazione. Quando ASP.NET MVC tenta di risolvere un modello di visualizzazione, verifica prima di tutto nella directory specifica \Views[Controller] e, se non riesce a trovare il modello di visualizzazione, verrà esaminato nella directory \Views\Shared .
Quando si tratta di assegnare un nome ai singoli modelli di visualizzazione, le indicazioni consigliate sono la condivisione del modello di visualizzazione con lo stesso nome del metodo di azione che ne ha causato il rendering. Ad esempio, sopra il metodo di azione "Index" viene usata la visualizzazione "Index" per eseguire il rendering del risultato della visualizzazione e il metodo di azione "Dettagli" usa la visualizzazione "Dettagli" per eseguire il rendering dei risultati. Ciò semplifica la visualizzazione rapida del modello associato a ogni azione.
Gli sviluppatori non devono specificare in modo esplicito il nome del modello di visualizzazione quando il modello di visualizzazione ha lo stesso nome del metodo di azione richiamato nel controller. È invece possibile passare l'oggetto modello al metodo helper "View()" (senza specificare il nome della visualizzazione) e ASP.NET MVC dedurrà automaticamente che si vuole usare il modello di visualizzazione \Views[ControllerName][ActionName] sul disco per eseguirne il rendering.
In questo modo è possibile pulire leggermente il codice del controller ed evitare di duplicare il nome due volte nel codice:
public class DinnersController : Controller {
DinnerRepository dinnerRepository = new DinnerRepository();
//
// GET: /Dinners/
public ActionResult Index() {
var dinners = dinnerRepository.FindUpcomingDinners().ToList();
return View(dinners);
}
//
// GET: /Dinners/Details/2
public ActionResult Details(int id) {
Dinner dinner = dinnerRepository.GetDinner(id);
if (dinner == null)
return View("NotFound");
else
return View(dinner);
}
}
Il codice precedente è tutto ciò che è necessario per implementare un'esperienza di presentazione/dettagli della cena piacevole per il sito.
passaggio successivo
Ora abbiamo una bella esperienza di navigazione cena costruito.
A questo punto è possibile abilitare il supporto per la modifica dei moduli dati CRUD (Create, Read, Update, Delete).