搜尋

注意

本教學課程的更新版本 可在這裡 使用最新版本的 Visual Studio。 新的教學課程會使用ASP.NET Core MVC,這可針對本教學課程提供許多改善。

本教學課程可讓您了解 ASP.NET Core MVC 與控制器和檢視。 Razor Pages 是 ASP.NET Core 的新替代方案,這是頁面型程式設計模型,可讓建置 Web UI 變得更簡單且更具生產力。 建議您在嘗試使用 MVC 版本之前,先試試 Razor 頁面教學課程。 Razor 頁面教學課程:

  • 比較容易學習。
  • 涵蓋更多功能。
  • 這是新應用程式開發的慣用方法。

新增搜尋方法和搜尋檢視

在本節中,您會將搜尋功能新增至 Index 動作方法,讓您依內容類型或名稱搜尋電影。

必要條件

若要符合本節的螢幕擷取畫面,您必須執行應用程式 (F5) ,並將下列電影新增至資料庫。

標題 發行日期 Genre 價格
Ghostbusters 6/8/1984 喜劇 6.99
Ghostbusters II 6/16/1989 喜劇 6.99
Apes 的行星 3/27/1986 動作 5.99

更新索引表單

首先,將 Index 動作方法更新至現有的 MoviesController 類別。 此程式碼如下:

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

方法的第一行 Index 會建立下列 LINQ 查詢來選取電影:

var movies = from m in db.Movies 
                 select m;

此時會定義查詢,但尚未針對資料庫執行。

searchString如果參數包含字串,則會修改電影查詢,以使用下列程式碼篩選搜尋字串的值:

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

上述 s => s.Title 程式碼是 Lambda 運算式。 Lambda 用於以方法為基礎的 LINQ 查詢,作為標準查詢運算子方法的引數,例如上述程式碼中使用的 Where 方法。 LINQ 查詢在定義時,或藉由呼叫 或 OrderByWhere 方法來修改 LINQ 查詢時,不會執行查詢。 相反地,查詢執行會延遲,這表示運算式的評估會延遲,直到實際逐一查看其實現值或 ToList 呼叫 方法為止。 在範例中 Search ,查詢會在 Index.cshtml 檢視中執行。 如需延後查詢執行的詳細資訊,請參閱查詢執行

注意

Contains方法是在資料庫上執行,而不是上述 c# 程式碼。 在資料庫上, Contains 會 對應至不區分大小寫的 SQL LIKE

現在您可以更新 Index 顯示表單給使用者的檢視。

執行應用程式並流覽至 /Movies/Index。 將查詢字串 (例如 ?searchString=ghost) 附加至 URL。 隨即顯示篩選過的電影。

SearchQryStr

如果您將 方法的 Index 簽章變更為具有名為 id 的參數,參數 id 將會符合 {id}App_Start\RouteConfig.cs 檔案中所設定之預設路由的預留位置。

{controller}/{action}/{id}

原始 Index 方法看起來像這樣::

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

修改 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); 
}

您現在可以將搜尋標題作為路由資料 (URL 區段) 傳遞,而不是作為查詢字串值。

顯示 [M V C 電影索引] 頁面的螢幕擷取畫面。本機主機冒號 1 2 3 4 正斜線電影正斜線索引斜線准刪除位於 U R L 欄位中,並以紅色圓圈。

但是,您不能期望使用者在每次想要搜尋電影時修改 URL。 因此,現在您將新增可協助他們篩選電影的 UI。 如果您變更方法的 Index 簽章以測試如何傳遞路由系結識別碼參數,請將它變更回 ,讓您的 Index 方法採用名為 的 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); 
}

開啟 Views\Movies\Index.cshtml 檔案,然後在 之後 @Html.ActionLink("Create New", "Create") ,新增以下醒目提示的表單標記:

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

協助 Html.BeginForm 程式會建立開頭 <form> 標記。 協助 Html.BeginForm 程式會在使用者按一下 [ 篩選 ] 按鈕來提交表單時,讓表單自行張貼。

Visual Studio 2013在顯示和編輯檢視檔案時有良好的改善。 當您執行開啟檢視檔案的應用程式時,Visual Studio 2013叫用正確的控制器動作方法來顯示檢視。

顯示 [索引點 c s h t m l] 索引標籤並方案總管開啟的螢幕擷取畫面。在方案總管中,子資料夾 Movies 隨即開啟,並選取 [索引點 c s h t m l]。

在 Visual Studio 中開啟 [索引] 檢視 (,如上圖所示) ,點選 Ctr F5 或 F5 以執行應用程式,然後嘗試搜尋電影。

顯示 [索引] 頁面的螢幕擷取畫面,其中已輸入 [標題] 欄位的標題。

方法沒有 HttpPost 多載 Index 。 您不需要它,因為方法不會變更應用程式的狀態,只是篩選資料。

您可以新增下列 HttpPost Index 方法。 在此情況下,動作叫用程式會符合 HttpPost Index 方法,而且 方法 HttpPost Index 會執行,如下圖所示。

[HttpPost] 
public string Index(FormCollection fc, string searchString) 
{ 
    return "<h3> From [HttpPost]Index: " + searchString + "</h3>"; 
}

SearchPostGhost

不過,即使您新增這個 HttpPost 版本的 Index 方法,在如何全部實作此方法方面仍然有其限制。 假設您想要將特定的搜尋加為書籤,或者想要傳送連結給朋友,讓他們可以點選來查看相同的電影篩選清單。 請注意,HTTP POST 要求的 URL 與 GET 要求的 URL 相同, (localhost:xxxxx/Movies/Index) -- URL 本身沒有搜尋資訊。 現在,搜尋字串資訊會以表單欄位值的形式傳送至伺服器。 這表示您無法擷取搜尋資訊,將搜尋資訊加入書簽或傳送給 URL 中的朋友。

解決方案是使用 的多載 BeginForm ,指定 POST 要求應該將搜尋資訊新增至 URL,而且應該路由至 HttpGet 方法的版本 Index 。 以下列標記取代現有的無 BeginForm 參數方法:

@using (Html.BeginForm("Index","Movies",FormMethod.Get))

BeginFormPost_SM

現在當您提交搜尋時,URL 會包含搜尋查詢字串。 即使您有 HttpPost Index 方法,搜尋也會移至 HttpGet Index 動作方法。

IndexWithGetURL

依內容類型新增搜尋

如果您已新增 HttpPost 方法的版本 Index ,請立即將其刪除。

接下來,您將新增功能,讓使用者依內容類型搜尋電影。 以下列程式碼取代 Index 方法:

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

這個版本的 Index 方法會採用其他參數,也就是 movieGenre 。 前幾行程式碼會建立 List 物件,以保存資料庫中的電影內容類型。

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

var GenreQry = from d in db.Movies 
                   orderby d.Genre 
                   select d.Genre;

程式碼會 AddRange 使用泛型 List 集合的 方法,將所有不同的內容類型新增至清單。 (如果沒有 Distinct 修飾詞,則會新增重複的內容類型,例如,在我們的範例中會新增兩次 comedy) 。 然後,程式碼會將內容類型清單儲存在 物件中 ViewBag.MovieGenre 。 將類別資料儲存 (這類電影內容類型) 為 中的 ViewBagSelectList物件,然後在下拉式清單方塊中存取類別資料是 MVC 應用程式的一般方法。

下列程式碼示範如何檢查 movieGenre 參數。 如果不是空的,程式碼會進一步限制電影查詢,以將選取的電影限制為指定的內容類型。

if (!string.IsNullOrEmpty(movieGenre))
{
    movies = movies.Where(x => x.Genre == movieGenre);
}

如先前所述,在動作方法傳回) 之後 Index ,影片清單會逐一查看檢視中發生的 (,否則不會在資料庫上執行查詢。

將標記新增至索引檢視,以支援依內容類型搜尋

Html.DropDownList在協助程式之前 TextBox ,將協助程式新增至Views\Movies\Index.cshtml檔案。 完成的標記如下所示:

@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">

在下列程式碼中:

@Html.DropDownList("movieGenre", "All")

參數 「MovieGenre」 提供協助程式在 中尋找 IEnumerable<SelectListItem>ViewBag 索引鍵 DropDownListViewBag已在動作方法中填入 :

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

參數 「All」 提供選項標籤。 如果您在瀏覽器中檢查該選擇,您會看到其「值」屬性是空的。 由於我們的控制器只會篩選 if 字串不是 null 或空白,因此提交空白值以顯示 movieGenre 所有內容類型。

您也可以預設設定要選取的選項。 如果您想要 「Comedy」 作為預設選項,您會變更控制器中的程式碼,如下所示:

ViewBag.movieGenre = new SelectList(GenreLst, "Comedy");

執行應用程式並流覽至 /Movies/Index。 依內容類型、電影名稱及兩個準則嘗試搜尋。

顯示 [索引] 頁面的螢幕擷取畫面。已選取內容類型類型。

在本節中,您已建立搜尋動作方法和檢視,讓使用者依電影標題和內容類型搜尋。 在下一節中,您將瞭解如何將屬性新增至 Movie 模型,以及如何新增將會自動建立測試資料庫的初始化運算式。