Wyszukaj
Uwaga
Zaktualizowana wersja tego samouczka jest dostępna tutaj przy użyciu najnowszej wersji programu Visual Studio. W nowym samouczku użyto ASP.NET Core MVC, co zapewnia wiele ulepszeń w tym samouczku.
W tym samouczku przedstawiono ASP.NET Core MVC z kontrolerami i widokami. Razor Pages to nowa alternatywa w ASP.NET Core, oparty na stronach model programowania, który ułatwia tworzenie internetowego interfejsu użytkownika i bardziej wydajne. Zalecamy wypróbowanie samouczka Razor Pages przed wersją MVC. Samouczek usługi Razor Pages:
- Jest łatwiejsze do naśladowania.
- Obejmuje więcej funkcji.
- Jest preferowanym podejściem do tworzenia nowych aplikacji.
Dodawanie metody wyszukiwania i widoku wyszukiwania
W tej sekcji dodasz możliwość wyszukiwania do Index
metody akcji, która umożliwia wyszukiwanie filmów według gatunku lub nazwy.
Wymagania wstępne
Aby dopasować zrzuty ekranu tej sekcji, należy uruchomić aplikację (F5) i dodać następujące filmy do bazy danych.
Tytuł | Data wydania | Gatunek | Cena |
---|---|---|---|
Ghostbusters | 6/8/1984 | Komedia | 6.99 |
Ghostbusters II | 6/16/1989 | Komedia | 6.99 |
Planeta apes | 3/27/1986 | Akcja | 5,99 |
Aktualizowanie formularza indeksu
Rozpocznij od zaktualizowania Index
metody akcji do istniejącej MoviesController
klasy. Oto kod:
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);
}
Pierwszy wiersz Index
metody tworzy następujące zapytanie LINQ , aby wybrać filmy:
var movies = from m in db.Movies
select m;
Zapytanie jest zdefiniowane w tym momencie, ale nie zostało jeszcze uruchomione względem bazy danych.
searchString
Jeśli parametr zawiera ciąg, zapytanie filmów jest modyfikowane w celu filtrowania wartości ciągu wyszukiwania przy użyciu następującego kodu:
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
Powyższy s => s.Title
kod to wyrażenie lambda. Lambdas są używane w zapytaniach LINQ opartych na metodach jako argumentach do standardowych metod operatorów zapytań, takich jak metoda Where używana w powyższym kodzie. Zapytania LINQ nie są wykonywane, gdy są zdefiniowane lub kiedy są modyfikowane przez wywołanie metody, takiej jak Where
lub OrderBy
. Zamiast tego wykonanie zapytania jest odroczone, co oznacza, że ocena wyrażenia jest opóźniona do momentu, aż jego zrealizowana wartość zostanie rzeczywiście iteracji lub ToList
wywołana metoda. W przykładzie Search
zapytanie jest wykonywane w widoku Index.cshtml . Aby uzyskać więcej informacji na temat odroczonego wykonywania zapytań, zobacz Wykonywanie zapytań.
Uwaga
Metoda Contains jest uruchamiana w bazie danych, a nie w powyższym kodzie c#. W bazie danych zawiera mapowania na SQL LIKE, co jest bez uwzględniania wielkości liter.
Teraz możesz zaktualizować Index
widok, który wyświetli formularz użytkownikowi.
Uruchom aplikację i przejdź do folderu /Movies/Index. Dołącz ciąg zapytania, taki jak ?searchString=ghost
adres URL. Zostaną wyświetlone przefiltrowane filmy.
Jeśli zmienisz podpis Index
metody na parametr o nazwie id
, id
parametr będzie zgodny {id}
z symbolem zastępczym tras domyślnych ustawionych w pliku App_Start\RouteConfig.cs .
{controller}/{action}/{id}
Oryginalna Index
metoda wygląda następująco:
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);
}
Zmodyfikowana metoda wygląda następująco Index
:
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);
}
Teraz możesz przekazać tytuł wyszukiwania jako dane trasy (segment adresu URL) zamiast jako wartość ciągu zapytania.
Nie można jednak oczekiwać, że użytkownicy będą modyfikować adres URL za każdym razem, gdy chcą wyszukać film. Teraz dodasz interfejs użytkownika, aby ułatwić filtrowanie filmów. Jeśli zmieniono sygnaturę metody, aby przetestować sposób przekazywania parametru Index
identyfikatora powiązanego z trasą, zmień go z powrotem, aby Index
metoda przyjmuje parametr ciągu o nazwie 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);
}
Otwórz plik Views\Movies\Index.cshtml , a tuż po @Html.ActionLink("Create New", "Create")
pliku dodaj znacznik formularza wyróżniony poniżej:
@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>
Pomocnik Html.BeginForm
tworzy tag otwierający <form>
. Pomocnik Html.BeginForm
powoduje, że formularz zostanie przesłany do samego siebie, gdy użytkownik prześle formularz, klikając przycisk Filtruj .
Visual Studio 2013 ma miłą poprawę podczas wyświetlania i edytowania plików widoku. Po uruchomieniu aplikacji z otwartym plikiem widoku Visual Studio 2013 wywołuje prawidłową metodę akcji kontrolera w celu wyświetlenia widoku.
Po otwarciu widoku indeksu w programie Visual Studio (jak pokazano na powyższym obrazie), naciśnij pozycję Ctr F5 lub F5, aby uruchomić aplikację, a następnie spróbuj wyszukać film.
Nie HttpPost
ma przeciążenia Index
metody. Nie jest to potrzebne, ponieważ metoda nie zmienia stanu aplikacji, po prostu filtrując dane.
Możesz dodać następującą HttpPost Index
metodę. W takim przypadku wywołanie akcji będzie zgodne z HttpPost Index
metodą, a HttpPost Index
metoda zostanie uruchomiona, jak pokazano na poniższej ilustracji.
[HttpPost]
public string Index(FormCollection fc, string searchString)
{
return "<h3> From [HttpPost]Index: " + searchString + "</h3>";
}
Jednak nawet jeśli dodasz tę HttpPost
wersję metody, istnieje ograniczenie sposobu, w jaki wszystkie te elementy Index
zostały zaimplementowane. Załóżmy, że chcesz dodać zakładkę do określonego wyszukiwania lub chcesz wysłać link do znajomych, którzy mogą kliknąć, aby wyświetlić tę samą filtrowaną listę filmów. Zwróć uwagę, że adres URL żądania HTTP POST jest taki sam jak adres URL żądania GET (localhost:xxxxx/Movies/Index) — nie ma żadnych informacji wyszukiwania w samym adresie URL. W tej chwili informacje o ciągu wyszukiwania są wysyłane do serwera jako wartość pola formularza. Oznacza to, że nie można przechwycić tych informacji wyszukiwania do zakładki ani wysłać do znajomych w adresie URL.
Rozwiązaniem jest użycie przeciążenia BeginForm
, które określa, że żądanie POST powinno dodać informacje wyszukiwania do adresu URL i że powinno być kierowane do HttpGet
wersji Index
metody . Zastąp istniejącą metodę bez BeginForm
parametrów następującym znacznikiem:
@using (Html.BeginForm("Index","Movies",FormMethod.Get))
Teraz po przesłaniu wyszukiwania adres URL zawiera ciąg zapytania wyszukiwania. Wyszukiwanie spowoduje również przejście do HttpGet Index
metody akcji, nawet jeśli masz metodę HttpPost Index
.
Dodawanie wyszukiwania według gatunku
Jeśli dodano HttpPost
wersję Index
metody, usuń ją teraz.
Następnie dodasz funkcję umożliwiającą użytkownikom wyszukiwanie filmów według gatunku. Zastąp metodę Index
poniższym kodem:
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);
}
Ta wersja Index
metody przyjmuje dodatkowy parametr, czyli movieGenre
. Kilka pierwszych wierszy kodu tworzy List
obiekt do przechowywania gatunków filmów z bazy danych.
Poniższy kod to zapytanie LINQ, które pobiera wszystkie gatunki z bazy danych.
var GenreQry = from d in db.Movies
orderby d.Genre
select d.Genre;
Kod używa AddRange
metody kolekcji ogólnej List
, aby dodać wszystkie odrębne gatunki do listy. (Bez Distinct
modyfikatora zostaną dodane zduplikowane gatunki — na przykład komedia zostanie dodana dwa razy w naszym przykładzie). Następnie kod przechowuje listę gatunków w ViewBag.MovieGenre
obiekcie. Przechowywanie danych kategorii (takich gatunków filmów) jako obiektu SelectList w obiekcie ViewBag
, a następnie uzyskiwanie dostępu do danych kategorii w polu listy rozwijanej jest typowym podejściem dla aplikacji MVC.
Poniższy kod pokazuje, jak sprawdzić movieGenre
parametr. Jeśli nie jest on pusty, kod dodatkowo ogranicza zapytanie do filmów, aby ograniczyć wybrane filmy do określonego gatunku.
if (!string.IsNullOrEmpty(movieGenre))
{
movies = movies.Where(x => x.Genre == movieGenre);
}
Jak wspomniano wcześniej, zapytanie nie jest uruchamiane w bazie danych, dopóki lista filmów nie zostanie iterowana (co dzieje się w widoku, po Index
powrocie metody akcji).
Dodawanie znaczników do widoku indeksu w celu obsługi wyszukiwania według gatunku
Html.DropDownList
Dodaj pomocnika do pliku Views\Movies\Index.cshtml tuż przed pomocnikiemTextBox
. Ukończona adiustacja jest pokazana poniżej:
@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">
W poniższym kodzie:
@Html.DropDownList("movieGenre", "All")
Parametr "MovieGenre" zawiera klucz pomocnika DropDownList
do znalezienia elementu IEnumerable<SelectListItem>
w obiekcie ViewBag
. Element ViewBag
został wypełniony w metodzie akcji:
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);
}
Parametr "Wszystkie" zawiera etykietę opcji. Jeśli sprawdzisz ten wybór w przeglądarce, zobaczysz, że jego atrybut "value" jest pusty. Ponieważ kontroler filtruje if
tylko ciąg nie null
jest pusty lub nie jest pusty, przesyłając pustą wartość dla movieGenre
wszystkich gatunków.
Można również ustawić opcję domyślnie wybraną. Jeśli chcesz, aby opcja "Komedia" była opcją domyślną, należy zmienić kod w kontrolerze w następujący sposób:
ViewBag.movieGenre = new SelectList(GenreLst, "Comedy");
Uruchom aplikację i przejdź do folderu /Movies/Index. Spróbuj wyszukać według gatunku, nazwy filmu i obu kryteriów.
W tej sekcji utworzono metodę akcji wyszukiwania i widok, która umożliwia użytkownikom wyszukiwanie według tytułu filmu i gatunku. W następnej sekcji dowiesz się, jak dodać właściwość do Movie
modelu i jak dodać inicjator, który automatycznie utworzy testową bazę danych.