Condividi tramite


Ricerca

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.

SearchQryStr

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.

Screenshot che mostra la pagina M V C Movie Index. I due punti host locali 1 2 3 4 barre Film indice barra barra fantasma è nel campo U R L e cerchiato in rosso.

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.

Screenshot che mostra la scheda

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.

Screenshot che mostra la pagina Indice con un titolo immesso nel campo Titolo.

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>"; 
}

SearchPostGhost

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))

BeginFormPost_SM

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.

IndexWithGetURL

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.

Screenshot che mostra la pagina Indice. Viene selezionato un tipo di genere.

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.