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.
Annotazioni
Una versione aggiornata di questa esercitazione è disponibile qui usando la versione più recente di Visual Studio. La nuova esercitazione usa ASP.NET Core MVC, che offre molti miglioramenti in questa esercitazione.
Questa esercitazione illustra ASP.NET Core MVC con controller e visualizzazioni. Razor Pages è una nuova alternativa in ASP.NET Core, un modello di programmazione basato su pagine che semplifica la creazione dell'interfaccia utente Web e una maggiore produttività. È consigliabile provare l'esercitazione su Razor Pages prima della versione di MVC. Il tutorial su Razor Pages:
- È più facile da seguire.
- Vengono illustrate altre funzionalità.
- È l'approccio preferito per lo sviluppo di nuove app.
Aggiungere un metodo di ricerca e una visualizzazione di ricerca
In questa sezione si aggiungerà la funzionalità di ricerca al metodo di azione che consente di cercare film in base al Index genere o al nome.
Prerequisiti
Per trovare la corrispondenza con gli screenshot di questa sezione, è necessario eseguire l'applicazione (F5) e aggiungere i film seguenti al database.
| Titolo | Data di rilascio | Genere | prezzo |
|---|---|---|---|
| Ghostbusters | 6/8/1984 | Commedia | 6,99 |
| Ghostbusters II | 6/16/1989 | Commedia | 6,99 |
| Pianeta delle scimmie | 3/27/1986 | Action | 5,99 |
Aggiornamento del modulo indice
Per iniziare, aggiornare il Index metodo di azione alla classe esistente MoviesController . Ecco il codice:
public ActionResult Index(string searchString)
{
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
return View(movies);
}
La prima riga del Index metodo crea la query LINQ seguente per selezionare i film:
var movies = from m in db.Movies
select m;
La query viene definita a questo punto, ma non è ancora stata eseguita nel database.
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 (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
Il codice s => s.Title precedente è un'espressione lambda. Le lambda vengono usate nelle query LINQ basate su metodo come argomenti per metodi dell'operatore di query standard, ad esempio il metodo Where usato nel codice precedente. 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 è differita, il che significa che la valutazione di un'espressione viene ritardata fino a quando il valore realizzato non viene effettivamente sottoposto a iterazione o il metodo ToList viene chiamato. Nell'esempio Search la query viene eseguita nella vista Index.cshtml . Per altre informazioni sull'esecuzione posticipata di query, vedere Esecuzione di query.
Annotazioni
Il metodo Contains viene eseguito nel database, non nel codice c# precedente. Nel database, Contains mappa a SQL LIKE, che non fa distinzione tra maiuscole e minuscole.
È ora possibile aggiornare la Index visualizzazione che visualizzerà il modulo all'utente.
Eseguire l'applicazione e passare a /Movies/Index. Accodare una stringa di query, ad esempio ?searchString=ghost, all'URL. Vengono visualizzati i film filtrati.
Se si modifica la firma del Index metodo in modo che abbia un parametro denominato id, il id parametro corrisponderà al {id} segnaposto per le route predefinite impostate nel file App_Start\RouteConfig.cs .
{controller}/{action}/{id}
Il metodo originale Index è simile al seguente:
public ActionResult Index(string searchString)
{
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
return View(movies);
}
Il metodo modificato Index sarà simile al seguente:
public ActionResult Index(string id)
{
string searchString = id;
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
return View(movies);
}
È 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 Index metodo per verificare come passare il parametro ID associato a route, modificarla di nuovo in modo che il Index metodo prenda un parametro stringa denominato searchString:
public ActionResult Index(string searchString)
{
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
return View(movies);
}
Aprire il file Views\Movies\Index.cshtml e subito dopo @Html.ActionLink("Create New", "Create"), aggiungere il markup del modulo evidenziato di seguito:
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
@Html.ActionLink("Create New", "Create")
@using (Html.BeginForm()){
<p> Title: @Html.TextBox("SearchString") <br />
<input type="submit" value="Filter" /></p>
}
</p>
L'helper Html.BeginForm crea un tag di apertura <form> . L'helper Html.BeginForm fa in modo che il modulo invii i dati a se stesso quando l'utente invia il modulo facendo clic sul pulsante Filtro.
Visual Studio 2013 offre un miglioramento significativo durante la visualizzazione e la modifica dei file di visualizzazione. Quando si esegue l'applicazione con un file di visualizzazione aperto, Visual Studio 2013 richiama il metodo di azione del controller corretto per visualizzare la visualizzazione.
Con la visualizzazione Indice aperta in Visual Studio (come illustrato nell'immagine precedente), toccare Ctr F5 o F5 per eseguire l'applicazione e quindi provare a cercare un filmato.
Non esiste alcun HttpPost overload del Index metodo. Non è necessario, perché il metodo non modifica lo stato dell'applicazione, filtrando semplicemente i dati.
È possibile aggiungere il metodo HttpPost Index seguente. In tal caso, l'invoker di azione corrisponderebbe al metodo HttpPost Index e il metodo HttpPost Index verrebbe eseguito come mostrato nell'immagine sottostante.
[HttpPost]
public string Index(FormCollection fc, string searchString)
{
return "<h3> From [HttpPost]Index: " + searchString + "</h3>";
}
Tuttavia, anche se si aggiunge questa versione HttpPost del metodo Index, c'è una limitazione nel modo in cui è stata implementata. Si supponga che si desideri usare come segnalibro una ricerca specifica o inviare un collegamento agli amici su cui possono fare clic per visualizzare lo stesso elenco filtrato di film. Si noti che l'URL per la richiesta HTTP POST corrisponde all'URL della richiesta GET (localhost:xxxxx/Movies/Index). Non sono presenti informazioni di ricerca nell'URL stesso. Al momento, le informazioni sulla stringa di ricerca vengono inviate al server come valore di un campo del modulo. Ciò significa che non è possibile acquisire le informazioni di ricerca nel segnalibro o inviarle agli amici in un URL.
La soluzione consiste nell'usare un overload di BeginForm che specifica che la richiesta POST deve aggiungere le informazioni di ricerca all'URL e che deve essere instradata alla versione HttpGet del metodo Index. Sostituire il metodo senza parametri BeginForm esistente con il markup seguente:
@using (Html.BeginForm("Index","Movies",FormMethod.Get))
Ora quando si invia una ricerca, l'URL contiene una stringa di query di ricerca. La ricerca passerà anche al metodo di azione HttpGet Index, anche se si dispone di un metodo HttpPost Index.
Aggiunta della funzionalità di ricerca per genere
Se è stata aggiunta la HttpPost versione del Index metodo, eliminarla ora.
Successivamente, si aggiungerà una funzionalità per consentire agli utenti di cercare film per genere. Sostituire il Index metodo con il codice seguente:
public ActionResult Index(string movieGenre, string searchString)
{
var GenreLst = new List<string>();
var GenreQry = from d in db.Movies
orderby d.Genre
select d.Genre;
GenreLst.AddRange(GenreQry.Distinct());
ViewBag.movieGenre = new SelectList(GenreLst);
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
if (!string.IsNullOrEmpty(movieGenre))
{
movies = movies.Where(x => x.Genre == movieGenre);
}
return View(movies);
}
Questa versione del Index 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.
var GenreQry = from d in db.Movies
orderby 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.MovieGenre . L'archiviazione dei dati delle categorie (ad esempio generi di film) come oggetto SelectList in un ViewBagoggetto , quindi l'accesso ai dati delle categorie in una casella di riepilogo a discesa è un approccio tipico per le applicazioni MVC.
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))
{
movies = movies.Where(x => x.Genre == movieGenre);
}
Come indicato in precedenza, la query non viene eseguita nel database fino a quando non si scorre l'elenco dei film (che si verifica nella View, dopo che il metodo action Index viene restituito).
Aggiunta di markup alla visualizzazione indice per supportare la ricerca per genere
Aggiungere un Html.DropDownList helper al file Views\Movies\Index.cshtml, subito prima dell'helper TextBox. Il markup completato è illustrato di seguito:
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
@Html.ActionLink("Create New", "Create")
@using (Html.BeginForm("Index", "Movies", FormMethod.Get))
{
<p>
Genre: @Html.DropDownList("movieGenre", "All")
Title: @Html.TextBox("SearchString")
<input type="submit" value="Filter" />
</p>
}
</p>
<table class="table">
Nel codice seguente:
@Html.DropDownList("movieGenre", "All")
Il parametro "MovieGenre" fornisce la chiave al DropDownList helper per trovare un IEnumerable<SelectListItem> nel ViewBag. L'oggetto ViewBag è stato popolato nel metodo di azione:
public ActionResult Index(string movieGenre, string searchString)
{
var GenreLst = new List<string>();
var GenreQry = from d in db.Movies
orderby d.Genre
select d.Genre;
GenreLst.AddRange(GenreQry.Distinct());
ViewBag.movieGenre = new SelectList(GenreLst);
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
if (!string.IsNullOrEmpty(movieGenre))
{
movies = movies.Where(x => x.Genre == movieGenre);
}
return View(movies);
}
Il parametro "All" fornisce un'etichetta di opzione. Se si esamina tale scelta nel browser, si noterà che l'attributo "value" è vuoto. Poiché il controller filtra if solo la stringa non null è o vuota, l'invio di un valore vuoto per movieGenre mostra tutti i generi.
È anche possibile impostare un'opzione da selezionare per impostazione predefinita. Se si desidera "Comedy" come opzione predefinita, modificare il codice nel controller in questo modo:
ViewBag.movieGenre = new SelectList(GenreLst, "Comedy");
Eseguire l'applicazione e passare a /Movies/Index. Provare una ricerca per genere, per nome del film e per entrambi i criteri.
In questa sezione è 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.