第6部分:將搜尋新增至 ASP.NET Core Razor 頁面

作者:Rick Anderson

在下列各節中,會新增依「內容類型」或「名稱」搜尋電影。

將下列反白顯示的程式碼新增至 Pages/電影/ Index cshtml

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace RazorPagesMovie.Pages.Movies
{
    public class IndexModel : PageModel
    {
        private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

        public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
        {
            _context = context;
        }

        public IList<Movie> Movie { get; set; }
        [BindProperty(SupportsGet = true)]
        public string SearchString { get; set; }
        public SelectList Genres { get; set; }
        [BindProperty(SupportsGet = true)]
        public string MovieGenre { get; set; }

在先前的程式碼中:

  • SearchString:包含使用者在 [搜尋] 文字方塊中輸入的文字。 SearchString 具有 [BindProperty] 屬性。 [BindProperty] 使用與屬性相同的名稱來繫結表單值和查詢字串。 [BindProperty(SupportsGet = true)] 在 HTTP GET 要求上進行系結是必要的。
  • Genres:包含內容清單。 Genres 可讓使用者從清單中選取內容類型。 SelectList 需要 using Microsoft.AspNetCore.Mvc.Rendering;
  • MovieGenre:包含使用者選取的特定內容類型。 例如,"西方"。
  • 稍後在本教學課程中將會使用 GenresMovieGenre

警告

基於安全性考量,您必須選擇將 GET 要求資料繫結到頁面模型屬性。 請先驗證使用者輸入再將其對應至屬性。 當您 GET 針對依賴查詢字串或路由值的案例進行定址時,加入宣告系結會很有用。

若要系結要求的屬性 GET ,請將屬性 [BindProperty]SupportsGet 屬性設定為 true

[BindProperty(SupportsGet = true)]

如需詳細資訊,請參閱 ASP.NET Core 社區站立會議: (YouTube) 的系結取得討論。

Index以下列程式碼更新頁面的 OnGetAsync 方法:

public async Task OnGetAsync()
{
    var movies = from m in _context.Movie
                 select m;
    if (!string.IsNullOrEmpty(SearchString))
    {
        movies = movies.Where(s => s.Title.Contains(SearchString));
    }

    Movie = await movies.ToListAsync();
}

OnGetAsync 方法的第一行會建立 LINQ 查詢,以選取電影:

// using System.Linq;
var movies = from m in _context.Movie
             select m;

此查詢僅限 *定義 _,此時會針對資料庫執行 _ *not**。

如果 SearchString 屬性不是 Null 或空白,則會修改電影查詢來篩選搜尋字串:

if (!string.IsNullOrEmpty(SearchString))
{
    movies = movies.Where(s => s.Title.Contains(SearchString));
}

s => s.Title.Contains() 程式碼是一種 Lambda 運算式。 在以方法為基礎的 LINQ 查詢中,lambda 會用來作為標準查詢運算子方法的引數,例如 Where 方法或 Contains 。 在定義 LINQ 查詢時,或藉由呼叫方法(例如、或)進行修改時,不會執行 LINQ 查詢 Where Contains OrderBy 。 而會延後執行查詢。 運算式的評估會延遲,直到反覆運算其實現值或 ToListAsync 呼叫方法為止。 如需詳細資訊,請參閱查詢執行

注意

Contains 方法是在資料庫上執行,而不是在 C# 程式碼中執行。 查詢是否區分大小寫取決於資料庫和定序。 在 SQL Server 上,Contains 對應至 SQL LIKE,因此不區分大小寫。 具有預設定序的 SQLite 是區分大小寫 和區分大小寫的 組合(視查詢而定)。 如需有關如何進行不區分大小寫的 SQLite 查詢的詳細資訊,請參閱下列內容:

流覽至 [電影] 頁面,並將查詢字串(例如)附加 ?searchString=Ghost 至 URL。 例如: https://localhost:5001/Movies?searchString=Ghost 。 隨即顯示篩選過的電影。

:::非 loc (索引) ::: view

如果將下列路由範本新增至 Index 頁面,則可以將搜尋字串作為 URL 區段傳遞。 例如: https://localhost:5001/Movies/Ghost

@page "{searchString?}"

上述的路由條件約束可讓您以路由資料的形式 (URL 區段) 搜尋標題,而不是以查詢字串值的形式。 在 ? 中,"{searchString?}" 表示此為選擇性的路由參數。

:::非 loc (索引) ::: view 加上自動加到 Url 的字組和傳回的電影清單(Ghostbusters 和 Ghostbusters 2)

ASP.NET Core 執行階段使用模型繫結來設定查詢字串 (?searchString=Ghost) 中的 SearchString 屬性值或路由傳送資料 (https://localhost:5001/Movies/Ghost)。 模型系結 區分大小寫。

但是,使用者無法修改 URL 來搜尋電影。 在此步驟中,會新增用來篩選電影的 UI。 如果您已新增路由條件約束 "{searchString?}",請將它移除。

開啟 Pages/電影/ Index cshtml 檔案,並新增下列程式碼中反白顯示的標記:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>

<form>
    <p>
        Title: <input type="text" asp-for="SearchString" />
        <input type="submit" value="Filter" />
    </p>
</form>

<table class="table">
    @*Markup removed for brevity.*@

HTML <form> 標籤會使用下列標籤協助程式

儲存變更並測試篩選條件。

:::非 loc (索引) ::: view 加上具類型的字組至標題篩選文字方塊

依內容類型搜尋

Index以下列程式碼更新頁面的 OnGetAsync 方法:

public async Task OnGetAsync()
{
    // Use LINQ to get list of genres.
    IQueryable<string> genreQuery = from m in _context.Movie
                                    orderby m.Genre
                                    select m.Genre;

    var movies = from m in _context.Movie
                 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);
    }
    Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
    Movie = await movies.ToListAsync();
}

下列程式碼是一種 LINQ 查詢,其會從資料庫中擷取所有的內容類型。

// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
                                orderby m.Genre
                                select m.Genre;

內容類型的 SelectList 是由投影不同的內容類型來建立。

Genres = new SelectList(await genreQuery.Distinct().ToListAsync());

將依內容類型搜尋新增至 Razor 頁面

在下列標記中,以反白顯示的方式更新 Index cshtml <form> 元素

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>

<form>
    <p>
        <select asp-for="MovieGenre" asp-items="Model.Genres">
            <option value="">All</option>
        </select>
        Title: <input type="text" asp-for="SearchString" />
        <input type="submit" value="Filter" />
    </p>
</form>

依據內容類型、電影標題和這兩者進行搜尋,藉以測試應用程式。

在下列各節中,會新增依「內容類型」或「名稱」搜尋電影。

將下列反白顯示的 using 語句和屬性新增至 Pages/電影/ Index cshtml

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace RazorPagesMovie.Pages.Movies
{

    public class IndexModel : PageModel
    {
        private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

        public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
        {
            _context = context;
        }

        public IList<Movie> Movie { get; set; }
        [BindProperty(SupportsGet = true)]
        public string SearchString { get; set; }
        public SelectList Genres { get; set; }
        [BindProperty(SupportsGet = true)]
        public string MovieGenre { get; set; }

在先前的程式碼中:

  • SearchString:包含使用者在 [搜尋] 文字方塊中輸入的文字。 SearchString 具有 [BindProperty] 屬性。 [BindProperty] 使用與屬性相同的名稱來繫結表單值和查詢字串。 [BindProperty(SupportsGet = true)] 在 HTTP GET 要求上進行系結是必要的。
  • Genres:包含內容清單。 Genres 可讓使用者從清單中選取內容類型。 SelectList 需要 using Microsoft.AspNetCore.Mvc.Rendering;
  • MovieGenre:包含使用者選取的特定內容類型。 例如,"西方"。
  • 稍後在本教學課程中將會使用 GenresMovieGenre

警告

基於安全性考量,您必須選擇將 GET 要求資料繫結到頁面模型屬性。 請先驗證使用者輸入再將其對應至屬性。 當您 GET 針對依賴查詢字串或路由值的案例進行定址時,加入宣告系結會很有用。

若要系結要求的屬性 GET ,請將屬性 [BindProperty]SupportsGet 屬性設定為 true

[BindProperty(SupportsGet = true)]

如需詳細資訊,請參閱 ASP.NET Core 社區站立會議: (YouTube) 的系結取得討論。

Index以下列程式碼更新頁面的 OnGetAsync 方法:

public async Task OnGetAsync()
{
    var movies = from m in _context.Movie
                 select m;
    if (!string.IsNullOrEmpty(SearchString))
    {
        movies = movies.Where(s => s.Title.Contains(SearchString));
    }

    Movie = await movies.ToListAsync();
}

OnGetAsync 方法的第一行會建立 LINQ 查詢,以選取電影:

// using System.Linq;
var movies = from m in _context.Movie
             select m;

此查詢僅限 *定義 _,此時會針對資料庫執行 _ *not**。

如果 SearchString 屬性不是 Null 或空白,則會修改電影查詢來篩選搜尋字串:

if (!string.IsNullOrEmpty(SearchString))
{
    movies = movies.Where(s => s.Title.Contains(SearchString));
}

s => s.Title.Contains() 程式碼是一種 Lambda 運算式。 在以方法為基礎的 LINQ 查詢中,lambda 會用來作為標準查詢運算子方法的引數,例如 Where 方法或 Contains 。 在定義 LINQ 查詢時,或藉由呼叫方法(例如、或)進行修改時,不會執行 LINQ 查詢 Where Contains OrderBy 。 而會延後執行查詢。 運算式的評估會延遲,直到反覆運算其實現值或 ToListAsync 呼叫方法為止。 如需詳細資訊,請參閱查詢執行

注意

Contains 方法是在資料庫上執行,而不是在 C# 程式碼中執行。 查詢是否區分大小寫取決於資料庫和定序。 在 SQL Server 上,Contains 對應至 SQL LIKE,因此不區分大小寫。 具有預設定序的 SQLite 是區分大小寫 和區分大小寫的 組合(視查詢而定)。 如需有關如何進行不區分大小寫的 SQLite 查詢的詳細資訊,請參閱下列內容:

流覽至 [電影] 頁面,並將查詢字串(例如)附加 ?searchString=Ghost 至 URL。 例如: https://localhost:5001/Movies?searchString=Ghost 。 隨即顯示篩選過的電影。

:::非 loc (索引) ::: view

如果將下列路由範本新增至 Index 頁面,則可以將搜尋字串作為 URL 區段傳遞。 例如: https://localhost:5001/Movies/Ghost

@page "{searchString?}"

上述的路由條件約束可讓您以路由資料的形式 (URL 區段) 搜尋標題,而不是以查詢字串值的形式。 在 ? 中,"{searchString?}" 表示此為選擇性的路由參數。

:::非 loc (索引) ::: view 加上自動加到 Url 的字組和傳回的電影清單(Ghostbusters 和 Ghostbusters 2)

ASP.NET Core 執行階段使用模型繫結來設定查詢字串 (?searchString=Ghost) 中的 SearchString 屬性值或路由傳送資料 (https://localhost:5001/Movies/Ghost)。 模型系結 區分大小寫。

但是,使用者無法修改 URL 來搜尋電影。 在此步驟中,會新增用來篩選電影的 UI。 如果您已新增路由條件約束 "{searchString?}",請將它移除。

開啟 Pages/電影/ Index cshtml 檔案,並新增下列程式碼中反白顯示的標記:

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>

<form>
    <p>
        Title: <input type="text" asp-for="SearchString" />
        <input type="submit" value="Filter" />
    </p>
</form>

<table class="table">
    @*Markup removed for brevity.*@

HTML <form> 標籤會使用下列標籤協助程式

儲存變更並測試篩選條件。

:::非 loc (索引) ::: view 加上具類型的字組至標題篩選文字方塊

依內容類型搜尋

Index以下列程式碼更新頁面的 OnGetAsync 方法:

public async Task OnGetAsync()
{
    // Use LINQ to get list of genres.
    IQueryable<string> genreQuery = from m in _context.Movie
                                    orderby m.Genre
                                    select m.Genre;

    var movies = from m in _context.Movie
                 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);
    }
    Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
    Movie = await movies.ToListAsync();
}

下列程式碼是一種 LINQ 查詢,其會從資料庫中擷取所有的內容類型。

// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
                                orderby m.Genre
                                select m.Genre;

內容類型的 SelectList 是由投影不同的內容類型來建立。

Genres = new SelectList(await genreQuery.Distinct().ToListAsync());

將依內容類型搜尋新增至 Razor 頁面

  1. 在下列標記中,以反白顯示的方式更新 Index cshtml <form> 元素

    @page
    @model RazorPagesMovie.Pages.Movies.IndexModel
    
    @{
        ViewData["Title"] = "Index";
    }
    
    <h1>Index</h1>
    
    <p>
        <a asp-page="Create">Create New</a>
    </p>
    
    <form>
        <p>
            <select asp-for="MovieGenre" asp-items="Model.Genres">
                <option value="">All</option>
            </select>
            Title: <input type="text" asp-for="SearchString" />
            <input type="submit" value="Filter" />
        </p>
    </form>
    
    <table class="table">
        @*Markup removed for brevity.*@
    
    
  2. 依據內容類型、電影標題和這兩者進行搜尋,藉以測試應用程式。

其他資源