aspnetcore/tutorials/razor-pages/search.md
:::moniker range=">= aspnetcore-10.0"
In the following sections, you add the ability to search movies by genre or name.
Add the following highlighted code to Pages/Movies/Index.cshtml.cs:
In the previous code:
SearchString: Contains the text users enter in the search text box. SearchString has the [BindProperty] attribute. [BindProperty] binds form values and query strings with the same name as the property. [BindProperty(SupportsGet = true)] is required for binding on HTTP GET requests.Genres: Contains the list of genres. Genres allows the user to select a genre from the list. SelectList requires using Microsoft.AspNetCore.Mvc.Rendering;MovieGenre: Contains the specific genre the user selects. For example, "Western".Genres and MovieGenre are used later in this tutorial.Update the Movies/Index page's OnGetAsync method with the following code:
The first line of the OnGetAsync method creates a LINQ query to select the movies:
The query is only defined at this point. It isn't run against the database.
If the SearchString property isn't null or empty, the movies query is modified to filter on the search string:
The s => s.Title.Contains() code is a Lambda Expression. Lambdas are used in method-based LINQ queries as arguments to standard query operator methods such as the Where method or Contains. LINQ queries aren't executed when you define them or when you modify them by calling a method, such as Where, Contains, or OrderBy. Rather, query execution is deferred. The evaluation of an expression is delayed until its realized value is iterated over or the ToListAsync method is called. For more information, see Query Execution.
[!NOTE] The xref:System.Data.Objects.DataClasses.EntityCollection%601.Contains%2A method runs on the database, not in the C# code. The case sensitivity on the query depends on the database and the collation. On SQL Server,
Containsmaps to SQL LIKE, which is case insensitive. SQLite with the default collation is a mixture of case sensitive and case INsensitive, depending on the query. For information on making case insensitive SQLite queries, see the following:
Navigate to the Movies page and append a query string such as ?searchString=Ghost to the URL. For example, https://localhost:7247/Movies?searchString=Ghost. The filtered movies are displayed.
:::image type="content" source="~/tutorials/razor-pages/search/media/search-string-ghost.png" alt-text="Index view with the search string ghost in the URL and a returned movie list.":::
If you add the following route template to the Index page, you can pass the search string as a URL segment. For example, https://localhost:7247/Movies/Ghost.
@page "{searchString?}"
The preceding route constraint allows searching the title as route data (a URL segment) instead of as a query string value. The ? in "{searchString?}" means this is an optional route parameter.
:::image type="content" source="~/tutorials/razor-pages/search/media/ghost-title-route-data.png" alt-text="Index view with the word ghost added to the Url and a returned movie list of two movies, Ghostbusters and Ghostbusters 2.":::
The ASP.NET Core runtime uses model binding to set the value of the SearchString property from the query string (?searchString=Ghost) or route data (https://localhost:7247/Movies/Ghost). Model binding isn't case sensitive.
However, users can't be expected to modify the URL to search for a movie. In this step, you add UI to filter movies. If you added the route constraint "{searchString?}", remove it.
Open the Pages/Movies/Index.cshtml file, and add the markup highlighted in the following code:
The HTML <form> tag uses the following Tag Helpers:
Save your changes and test the filter.
:::image type="content" source="~/tutorials/razor-pages/search/media/filter-by-title.png" alt-text="Index view with the word ghost typed into the Title filter textbox.":::
Update the Movies/Index.cshtml.cs page OnGetAsync method with the following code:
The following code is a LINQ query that retrieves all the genres from the database.
The SelectList of genres is created by projecting the distinct genres:
Update the Index.cshtml <form> element as highlighted in the following markup:
Test the app by searching by genre, by movie title, and by both:
:::image type="content" source="~/tutorials/razor-pages/search/media/filter-by-genre-title.png" alt-text="Index view complete with Genre selector and Title textbox search filters.":::
[!div class="step-by-step"] Previous: Update the pages Next: Add a new field
:::moniker-end