AspNetCore.Docs/aspnetcore/includes/mvc-intro/search3.md

66 lines
3.3 KiB
Markdown
Raw Normal View History

<!--
[!code-html[](~/tutorials/first-mvc-app/start-mvc/sample/MvcMovie/Views/Shared/_Layout.cshtml?highlight=7,31)]
[!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/MvcMovie/Controllers/MoviesController.cs?name=snippet_1stSearch)]
[!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/MvcMovie/Controllers/MoviesController.cs?name=snippet_SearchNull)]
![Index view](~/tutorials/first-mvc-app/search/_static/ghost.png)
[!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/MvcMovie/Startup.cs?highlight=5&name=snippet_1)]
-->
Now when you submit a search, the URL contains the search query string. Searching will also go to the `HttpGet Index` action method, even if you have a `HttpPost Index` method.
![Browser window showing the searchString=ghost in the Url and the movies returned, Ghostbusters and Ghostbusters 2, contain the word ghost](~/tutorials/first-mvc-app/search/_static/search_get.png)
The following markup shows the change to the `form` tag:
```html
<form asp-controller="Movies" asp-action="Index" method="get">
```
## Adding Search by genre
Add the following `MovieGenreViewModel` class to the *Models* folder:
[!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/MvcMovie/Models/MovieGenreViewModel.cs)]
The movie-genre view model will contain:
* A list of movies.
* A `SelectList` containing the list of genres. This allows the user to select a genre from the list.
* `MovieGenre`, which contains the selected genre.
* `SearchString`, which contains the text users enter in the search text box.
Replace the `Index` method in `MoviesController.cs` with the following code:
[!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/MvcMovie/Controllers/MoviesController.cs?name=snippet_SearchGenre)]
The following code is a `LINQ` query that retrieves all the genres from the database.
[!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/MvcMovie/Controllers/MoviesController.cs?name=snippet_LINQ)]
The `SelectList` of genres is created by projecting the distinct genres (we don't want our select list to have duplicate genres).
When the user searches for the item, the search value is retained in the search box. To retain the search value, populate the `SearchString` property with the search value. The search value is the `searchString` parameter for the `Index` controller action.
```csharp
movieGenreVM.genres = new SelectList(await genreQuery.Distinct().ToListAsync())
```
## Adding search by genre to the Index view
Update `Index.cshtml` as follows:
[!code-HTML[](~/tutorials/first-mvc-app/start-mvc/sample/MvcMovie/Views/Movies/IndexFormGenreNoRating.cshtml?highlight=1,15,16,17,28,31,34,37,43)]
Examine the lambda expression used in the following HTML Helper:
`@Html.DisplayNameFor(model => model.Movies[0].Title)`
In the preceding code, the `DisplayNameFor` HTML Helper inspects the `Title` property referenced in the lambda expression to determine the display name. Since the lambda expression is inspected rather than evaluated, you don't receive an access violation when `model`, `model.Movies`, or `model.Movies[0]` are `null` or empty. When the lambda expression is evaluated (for example, `@Html.DisplayFor(modelItem => item.Title)`), the model's property values are evaluated.
Test the app by searching by genre, by movie title, and by both.