Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questa esercitazione illustra le nozioni di base per la creazione di un'applicazione Web MVC ASP.NET con Microsoft Visual Web Developer 2010 Express Service Pack 1, una versione gratuita di Microsoft Visual Studio. Prima di iniziare, assicurarsi di aver installato i prerequisiti elencati di seguito. È possibile installarli tutti facendo clic sul collegamento seguente: Programma di installazione della piattaforma Web. In alternativa, è possibile installare singolarmente i prerequisiti usando i collegamenti seguenti:
- Prerequisiti di Visual Studio Web Developer Express SP1
- ASP.NET aggiornamento degli strumenti MVC 3
- SQL Server Compact 4.0(runtime + tools support)
Se si usa Visual Studio 2010 anziché Visual Web Developer 2010, installare i prerequisiti facendo clic sul collegamento seguente: Prerequisiti di Visual Studio 2010.
Per questo argomento è disponibile un progetto Visual Web Developer con VB.NET codice sorgente. Scaricare la versione VB.NET. Se si preferisce C#, passare alla versione C# di questa esercitazione.
In questa sezione verranno esaminati i metodi di azione generati e le visualizzazioni per il controller di film. Si aggiungerà quindi una pagina di ricerca personalizzata.
Eseguire l'applicazione e passare al Movies controller aggiungendo /Movies all'URL nella barra degli indirizzi del browser. Tenere premuto il puntatore del mouse su un collegamento Modifica per visualizzare l'URL a cui si collega.

Il collegamento Edit è stato generato dal Html.ActionLink metodo nella vista Views\Movies\Index.vbhtml :
@Html.ActionLink("Edit", "Edit", New With {.id = currentItem.ID}) |
L'oggetto Html è un helper esposto usando una proprietà nella WebViewPage classe di base. Il ActionLink metodo dell'helper semplifica la generazione dinamica di collegamenti ipertestuali HTML che si collegano ai metodi di azione nei controller. Il primo argomento del metodo è il testo del collegamento di cui eseguire il ActionLink rendering, ad esempio <a>Edit Me</a>. Il secondo argomento è il nome del metodo di azione da richiamare. L'argomento finale è un oggetto anonimo che genera i dati della route (in questo caso, l'ID di 4).
Il collegamento generato visualizzato nell'immagine precedente è http://localhost:xxxxx/Movies/Edit/4. La route predefinita accetta il modello {controller}/{action}/{id}di URL . Pertanto, ASP.NET si traduce http://localhost:xxxxx/Movies/Edit/4 in una richiesta al Edit metodo di azione del Movies controller con il parametro ID uguale a 4.
È anche possibile passare parametri del metodo di azione usando una stringa di query. Ad esempio, l'URL http://localhost:xxxxx/Movies/Edit?ID=4 passa anche il parametro ID 4 al Edit metodo di azione del Movies controller.
Aprire il Movies controller. I due Edit metodi di azione sono illustrati di seguito.
'
' GET: /Movies/Edit/5
Function Edit(id As Integer) As ViewResult
Dim movie As Movie = db.Movies.Find(id)
Return View(movie)
End Function
'
' POST: /Movies/Edit/5
<HttpPost()>
Function Edit(movie As Movie) As ActionResult
If ModelState.IsValid Then
db.Entry(movie).State = EntityState.Modified
db.SaveChanges()
Return RedirectToAction("Index")
End If
Return View(movie)
End Function
Si noti che il secondo metodo di azione Edit è preceduto dall'attributo HttpPost. Questo attributo specifica che l'overload del Edit metodo può essere richiamato solo per le richieste POST. È possibile applicare l'attributo HttpGet al primo metodo di modifica, ma non è necessario perché è l'impostazione predefinita. Si farà riferimento ai metodi di azione assegnati in modo implicito all'attributo HttpGet come HttpGet metodi.
Il HttpGet Edit metodo accetta il parametro ID filmato, cerca il film usando il metodo Entity Framework Find e restituisce il filmato selezionato alla visualizzazione Modifica. Quando il sistema di scaffolding ha creato la vista Edit, ha esaminato la classe Movie e il codice creato per eseguire il rendering degli elementi <label> e <input> per ogni proprietà della classe. L'esempio seguente mostra la visualizzazione Edit generata:
@ModelType MvcMovie.Movie
@Code
ViewData("Title") = "Edit"
End Code
<h2>Edit</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@Using Html.BeginForm()
@Html.ValidationSummary(True)
@<fieldset>
<legend>Movie</legend>
@Html.HiddenFor(Function(model) model.ID)
<div class="editor-label">
@Html.LabelFor(Function(model) model.Title)
</div>
<div class="editor-field">
@Html.EditorFor(Function(model) model.Title)
@Html.ValidationMessageFor(Function(model) model.Title)
</div>
<div class="editor-label">
@Html.LabelFor(Function(model) model.ReleaseDate)
</div>
<div class="editor-field">
@Html.EditorFor(Function(model) model.ReleaseDate)
@Html.ValidationMessageFor(Function(model) model.ReleaseDate)
</div>
<div class="editor-label">
@Html.LabelFor(Function(model) model.Genre)
</div>
<div class="editor-field">
@Html.EditorFor(Function(model) model.Genre)
@Html.ValidationMessageFor(Function(model) model.Genre)
</div>
<div class="editor-label">
@Html.LabelFor(Function(model) model.Price)
</div>
<div class="editor-field">
@Html.EditorFor(Function(model) model.Price)
@Html.ValidationMessageFor(Function(model) model.Price)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
End Using
<div>
@Html.ActionLink("Back to List", "Index")
</div>
Si noti che il modello di visualizzazione dispone di un'istruzione @ModelType MvcMovie.Models.Movie all'inizio del file, che specifica che la vista prevede che il modello per il modello di visualizzazione sia di tipo Movie.
Il codice con scaffolding usa diversi metodi helper per semplificare il markup HTML. L'helper Html.LabelFor visualizza il nome del campo ("Title", "ReleaseDate", "Genre" o "Price"). L'helper Html.EditorFor visualizza un elemento HTML <input> . L'helper Html.ValidationMessageFor visualizza tutti i messaggi di convalida associati a tale proprietà.
Eseguire l'applicazione e passare all'URL /Movies . Fare clic su un collegamento Edit (Modifica). Nel browser visualizzare l'origine per la pagina. Il codice HTML nella pagina è simile all'esempio seguente. Il markup del menu è stato escluso per maggiore chiarezza.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Edit</title>
<link href="/Content/Site.css" rel="stylesheet" type="text/css" />
<script src="/Scripts/jquery-1.5.1.min.js" type="text/javascript"></script>
<script src="/Scripts/modernizr-1.7.min.js" type="text/javascript"></script>
</head>
<body>
<div class="page">
<header>
<div id="title">
<h1>MVC Movie App</h1>
</div>
...
</header>
<section id="main">
<h2>Edit</h2>
<script src="/Scripts/jquery.validate.min.js" type="text/javascript"></script>
<script src="/Scripts/jquery.validate.unobtrusive.min.js" type="text/javascript"></script>
<form action="/Movies/Edit/4" method="post"> <fieldset>
<legend>Movie</legend>
<input data-val="true" data-val-number="The field ID must be a number."
data-val-required="The ID field is required." id="ID" name="ID" type="hidden" value="4" />
<div class="editor-label">
<label for="Title">Title</label>
</div>
<div class="editor-field">
<input class="text-box single-line" id="Title" name="Title" type="text" value="Rio Bravo" />
<span class="field-validation-valid" data-valmsg-for="Title" data-valmsg-replace="true"></span>
</div>
<div class="editor-label">
<label for="ReleaseDate">ReleaseDate</label>
</div>
<div class="editor-field">
<input class="text-box single-line" data-val="true" data-val-required="The ReleaseDate field is required."
id="ReleaseDate" name="ReleaseDate" type="text" value="4/15/1959 12:00:00 AM" />
<span class="field-validation-valid" data-valmsg-for="ReleaseDate" data-valmsg-replace="true"></span>
</div>
<div class="editor-label">
<label for="Genre">Genre</label>
</div>
<div class="editor-field">
<input class="text-box single-line" id="Genre" name="Genre" type="text" value="Western" />
<span class="field-validation-valid" data-valmsg-for="Genre" data-valmsg-replace="true"></span>
</div>
<div class="editor-label">
<label for="Price">Price</label>
</div>
<div class="editor-field">
<input class="text-box single-line" data-val="true" data-val-number="The field Price must be a number."
data-val-required="The Price field is required." id="Price" name="Price" type="text" value="9.99" />
<span class="field-validation-valid" data-valmsg-for="Price" data-valmsg-replace="true"></span>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
</form>
<div>
<a href="/Movies">Back to List</a>
</div>
</section>
<footer>
</footer>
</div>
</body>
</html>
Gli <input> elementi si trovano in un elemento HTML <form> il cui action attributo è impostato per pubblicare l'URL /Movies/Edit . I dati del modulo verranno inseriti nel server quando si fa clic sul pulsante Modifica .
Elaborazione della richiesta POST
Nell'elenco seguente viene indicata la versione HttpPost del metodo di azione Edit.
'
' POST: /Movies/Edit/5
<HttpPost()>
Function Edit(movie As Movie) As ActionResult
If ModelState.IsValid Then
db.Entry(movie).State = EntityState.Modified
db.SaveChanges()
Return RedirectToAction("Index")
End If
Return View(movie)
End Function
Lo strumento di associazione di modelli del framework ASP.NET accetta i valori del modulo pubblicati e crea un Movie oggetto passato come movie parametro. Il ModelState.IsValid controllo nel codice verifica che i dati inviati nel modulo possano essere utilizzati per modificare un Movie oggetto. Se i dati sono validi, il codice salva i dati del filmato nella Movies raccolta dell'istanza MovieDBContext . Il codice salva quindi i nuovi dati dei film nel database chiamando il SaveChanges metodo di MovieDBContext, che rende persistenti le modifiche al database. Dopo aver salvato i dati, il codice reindirizza l'utente al Index metodo di azione della MoviesController classe , che fa sì che il filmato aggiornato venga visualizzato nell'elenco dei film.
Se i valori pubblicati non sono validi, vengono riprodotti nel formato. Gli Html.ValidationMessageFor helper nel modello di visualizzazione Edit.vbhtml si occupano della visualizzazione dei messaggi di errore appropriati.
Nota sulle impostazioni locali Se in genere si usano impostazioni locali diverse dall'inglese, vedere Supporto della convalida ASP.NET MVC 3 con impostazioni locali non in lingua inglese.
Rendere più affidabile il metodo edit
Il HttpGet Edit metodo generato dal sistema di scaffolding non verifica che l'ID passato sia valido. Se un utente rimuove il segmento ID dall'URL (http://localhost:xxxxx/Movies/Edit), viene visualizzato l'errore seguente:
Un utente può anche passare un ID che non esiste nel database, ad esempio http://localhost:xxxxx/Movies/Edit/1234. È possibile apportare due modifiche al HttpGet Edit metodo di azione per risolvere questa limitazione. Prima di tutto, modificare il ID parametro in modo che abbia un valore predefinito pari a zero quando un ID non viene passato in modo esplicito. È anche possibile verificare che il Find metodo ha effettivamente trovato un film prima di restituire l'oggetto film al modello di visualizzazione. Il metodo aggiornato Edit è illustrato di seguito.
Public Function Edit(Optional ByVal id As Integer = 0) As ActionResult
Dim movie As Movie = db.Movies.Find(id)
If movie Is Nothing Then
Return HttpNotFound()
End If
Return View(movie)
End Function
Se non viene trovato alcun filmato, viene chiamato il HttpNotFound metodo .
Tutti i HttpGet metodi seguono un modello simile. Ottengono un oggetto filmato (o un elenco di oggetti, nel caso di Index) e passano il modello alla visualizzazione. Il Create metodo passa un oggetto filmato vuoto alla visualizzazione Create. Tutti i metodi che creano, modificano, eliminano o cambiano in altro modo i dati, eseguono questa operazione nell'overload HttpPost del metodo. La modifica dei dati in un metodo HTTP GET è un rischio per la sicurezza. La modifica dei dati in un metodo GET viola anche le procedure consigliate HTTP e il modello REST dell'architettura, che specifica che le richieste GET non devono modificare lo stato dell'applicazione. In altre parole, l'esecuzione di un'operazione GET deve essere un'operazione sicura senza effetti collaterali.
Aggiunta di un metodo di ricerca e di una visualizzazione di ricerca
In questa sezione si aggiungerà un SearchIndex metodo di azione che consente di cercare film in base al genere o al nome. Sarà disponibile usando l'URL /Movies/SearchIndex . La richiesta visualizzerà un modulo HTML che contiene elementi di input che un utente può compilare per cercare un filmato. Quando un utente invia il modulo, il metodo di azione otterrà i valori di ricerca pubblicati dall'utente e userà i valori per eseguire ricerche nel database.

Visualizzazione del modulo SearchIndex
Per iniziare, aggiungere un SearchIndex metodo di azione alla classe esistente MoviesController . Il metodo restituirà una visualizzazione contenente un modulo HTML. Ecco il codice:
Public Function SearchIndex(ByVal searchString As String) As ActionResult
Dim movies = From m In db.Movies
Select m
If Not String.IsNullOrEmpty(searchString) Then
movies = movies.Where(Function(s) s.Title.Contains(searchString))
End If
Return View(movies)
End Function
La prima riga del SearchIndex metodo crea la query LINQ seguente per selezionare i film:
Dim movies = From m In db.Movies Select m
La query viene definita a questo punto, ma non è ancora stata eseguita nell'archivio dati.
Se il searchString parametro contiene una stringa, la query movies viene modificata per filtrare il valore della stringa di ricerca, usando il codice seguente:
If Not String.IsNullOrEmpty(searchString) Then
film = film. Where(Function(s.Title.Contains(searchString))
End If
Le query LINQ non vengono eseguite quando vengono definite o quando vengono modificate chiamando un metodo come Where o OrderBy. Al contrario, l'esecuzione della query viene posticipata, il che significa che la valutazione di un'espressione viene ritardata fino a quando il valore realizzato non viene effettivamente iterato o viene chiamato il ToList metodo . Nell'esempio SearchIndex la query viene eseguita nella vista SearchIndex. Per altre informazioni sull'esecuzione posticipata di query, vedere Esecuzione di query.
È ora possibile implementare la SearchIndex visualizzazione che visualizzerà il modulo all'utente. Fare clic con il pulsante destro del mouse all'interno del SearchIndex metodo e quindi scegliere Aggiungi visualizzazione. Nella finestra di dialogo Aggiungi visualizzazione specificare che si passerà un Movie oggetto al modello di visualizzazione come classe del modello di modello. Nell'elenco dei modelli di scaffolding scegliere Elenco, quindi fare clic su Aggiungi.
Quando si fa clic sul pulsante Aggiungi , viene creato il modello di visualizzazione Views\Movies\SearchIndex.vbhtml . Poiché è stato selezionato Elenco nell'elenco dei modelli di scaffolding, Visual Web Developer ha generato automaticamente (scaffolding) il contenuto predefinito nella visualizzazione. Lo scaffolding ha creato un modulo HTML. Ha esaminato la classe e creato il codice per eseguire il Movie rendering <label> degli elementi per ogni proprietà della classe . L'elenco seguente mostra la visualizzazione Crea generata:
@ModelType IEnumerable(Of MvcMovie.Movie)
@Code
ViewData("Title") = "SearchIndex"
End Code
<h2>SearchIndex</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
Title
</th>
<th>
ReleaseDate
</th>
<th>
Genre
</th>
<th>
Price
</th>
<th></th>
</tr>
@For Each item In Model
Dim currentItem = item
@<tr>
<td>
@Html.DisplayFor(Function(modelItem) currentItem.Title)
</td>
<td>
@Html.DisplayFor(Function(modelItem) currentItem.ReleaseDate)
</td>
<td>
@Html.DisplayFor(Function(modelItem) currentItem.Genre)
</td>
<td>
@Html.DisplayFor(Function(modelItem) currentItem.Price)
</td>
<td>
@Html.ActionLink("Edit", "Edit", New With {.id = currentItem.ID}) |
@Html.ActionLink("Details", "Details", New With {.id = currentItem.ID}) |
@Html.ActionLink("Delete", "Delete", New With {.id = currentItem.ID})
</td>
</tr>
Next
</table>
Eseguire l'applicazione e passare a /Movies/SearchIndex. Accodare una stringa di query, ad esempio ?searchString=ghost, all'URL. Vengono visualizzati i film filtrati.
Se si modifica la firma del SearchIndex metodo in modo che abbia un parametro denominato id, il id parametro corrisponderà al {id} segnaposto per le route predefinite impostate nel file Global.asax .
{controller}/{action}/{id}
Il metodo modificato SearchIndex sarà simile al seguente:
Public Function SearchIndex(ByVal id As String) As ActionResult
Dim searchString As String = id
Dim movies = From m In db.Movies
Select m
If Not String.IsNullOrEmpty(searchString) Then
movies = movies.Where(Function(s) s.Title.Contains(searchString))
End If
Return View(movies)
End Function
È ora possibile passare il titolo della ricerca come dati di route (un segmento di URL), anziché come valore della stringa di query.
Tuttavia, non è possibile supporre che gli utenti modifichino l'URL ogni volta che desiderano cercare un film. A questo punto si aggiungerà l'interfaccia utente per aiutarli a filtrare i film. Se è stata modificata la firma del SearchIndex metodo per verificare come passare il parametro ID associato a route, modificarla di nuovo in modo che il SearchIndex metodo prenda un parametro stringa denominato searchString:
Aprire il file Views\Movies\SearchIndex.vbhtml e, subito dopo @Html.ActionLink("Create New", "Create"), aggiungere quanto segue:
@Code
ViewData("Title") = "SearchIndex"
Using (Html.BeginForm())
@<p> Title: @Html.TextBox("SearchString")
<input type="submit" value="Filter" /></p>
End Using
End Code
L'helper Html.BeginForm crea un tag di apertura <form> . L'helper Html.BeginForm fa in modo che il modulo invii se stesso quando l'utente invia il modulo facendo clic sul pulsante Filtro .
Eseguire l'applicazione e provare a cercare un film.
Non esiste alcun HttpPost overload del SearchIndex metodo. Non è necessario, perché il metodo non modifica lo stato dell'applicazione, filtrando semplicemente i dati. Se è stato aggiunto il metodo seguente HttpPost SearchIndex, l'utilità di richiamo dell'azione corrisponde SearchIndex HttpPost al metodo e il HttpPost SearchIndex metodo verrà eseguito come illustrato nell'immagine seguente.
<HttpPost()>
Public Function SearchIndex(ByVal fc As FormCollection, ByVal searchString As String) As String
Return "<h3> From [HttpPost]SearchIndex: " & searchString & "</h3>"
End Function
Aggiunta della ricerca per genere
Se è stata aggiunta la HttpPost versione del SearchIndex metodo, eliminarla ora.
Successivamente, si aggiungerà una funzionalità per consentire agli utenti di cercare film per genere. Sostituire il metodo SearchIndex con il codice seguente:
Public Function SearchIndex(ByVal movieGenre As String, ByVal searchString As String) As ActionResult
Dim GenreLst = New List(Of String)()
Dim GenreQry = From d In db.Movies
Order By d.Genre
Select d.Genre
GenreLst.AddRange(GenreQry.Distinct())
ViewBag.movieGenre = New SelectList(GenreLst)
Dim movies = From m In db.Movies
Select m
If Not String.IsNullOrEmpty(searchString) Then
movies = movies.Where(Function(s) s.Title.Contains(searchString))
End If
If String.IsNullOrEmpty(movieGenre) Then
Return View(movies)
Else
Return View(movies.Where(Function(x) x.Genre = movieGenre))
End If
End Function
Questa versione del SearchIndex metodo accetta un parametro aggiuntivo, ovvero movieGenre. Le prime righe di codice creano un List oggetto per contenere generi di film dal database.
Il codice seguente è una query LINQ che recupera tutti i generi dal database.
Dim GenreQry = From d In db.Movies
Order By d.Genre
Select d.Genre
Il codice usa il AddRange metodo della raccolta generica List per aggiungere tutti i generi distinti all'elenco. (Senza il Distinct modificatore, verranno aggiunti generi duplicati, ad esempio, la commedia verrebbe aggiunta due volte nell'esempio). Il codice archivia quindi l'elenco dei generi nell'oggetto ViewBag .
Nel codice seguente viene illustrato come controllare il movieGenre parametro . Se non è vuoto, il codice vincola ulteriormente la query film per limitare i film selezionati al genere specificato.
If String.IsNullOrEmpty(movieGenre) Then
Return View(movies)
Else
Return View(movies.Where(Function(x) x.Genre = movieGenre))
End If
Aggiunta di markup alla visualizzazione SearchIndex per supportare la ricerca per genere
Aggiungere un Html.DropDownList helper al file Views\Movies\SearchIndex.vbhtml , subito prima dell'helper TextBox . Il markup completato è illustrato di seguito:
<p>
@Html.ActionLink("Create New", "Create")
@Code
ViewData("Title") = "SearchIndex"
Using (Html.BeginForm())
@<p> Genre: @Html.DropDownList("movieGenre", "All")
Title: @Html.TextBox("SearchString")
<input type="submit" value="Filter" /></p>
End Using
End Code
</p>
Eseguire l'applicazione e passare a /Movies/SearchIndex. Provare una ricerca per genere, per nome del film e per entrambi i criteri.
In questa sezione sono stati esaminati i metodi di azione CRUD e le viste generate dal framework. È stato creato un metodo di azione di ricerca e una visualizzazione che consente agli utenti di cercare in base al titolo e al genere del film. Nella sezione successiva verrà illustrato come aggiungere una proprietà al Movie modello e come aggiungere un inizializzatore che creerà automaticamente un database di test.








