[ASP.NET MVC] 在Index新增查詢功能,依照電影名稱與類型查詢電影。
修改Index Form
首先,先修改MoviesController的Index Action方法:
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參數不是Null或空值的話,將會修改movies的查詢來查詢searchString參數的值:
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
程式中 s => s.Title 為Lambda 表達式。
Lambda表達式作為LINQ查詢方法Where的參數來使用,LINQ在定義與修改時不會執行,而是到呼叫ToList方法時才有值。
在上面的例子中查詢語句會在Index.cshtml的@model IEnumerable<MyMVC.Models.Movie>才執行。
s => s.Title.Contains(searchString)表示依照searchString參數尋找Title包含參數字串的資料。
Where()的判斷標準為true或false,若判斷函式回傳true則成立,false則取消。
執行應用程式到/Movies/Index畫面,在網址列加上查詢字串?searchString=高年級,可以看到畫面:
在網址列中 ?searchString=高年級 的查詢字串,若要修改searchString參數與App_Start\RouteConfig.cs 中的 {controller}/{action}/{id} 的id參數對應。
可以將Index方法的參數名稱searchString改為id,這樣id參數就會匹配到RouteConfig中的{id}。
public ActionResult Index(string id)
{
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(id))
{
movies = movies.Where(s => s.Title.Contains(id));
}
return View(movies);
}
現在可以依照RouteConfig中的設定,將網址列改為 http://localhost:xxxxx/Movies/Index/高年級 。
查詢功能
接下來,將在Index頁面增加查詢功能。
將Index方法的參數從id改回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") 後面加上程式碼,加完後的程式碼如下:
<p>
@Html.ActionLink("Create New", "Create")
@using (Html.BeginForm())
{
<p> Title: @Html.TextBox("searchString")
<input type="submit" value="查詢" />
</p>
}
</p>
Html.BeginForm 會建立一個<Form>標籤,當點擊"查詢"按鈕時將表單提交回當前頁面。
執行應用程式,並試著查詢電影。
在MoviesController中並沒有[HttpPost]的Index方法,也不需要,因為只有做資料的查詢,沒有做資料的變更。
當然,也可以增加下面的[HttpPost]的Index方法。當點擊"查詢"按鈕submit表單時,便會呼叫[HttpPost]的Index方法,並回傳畫面。
[HttpPost]
public string Index(FormCollection fc, string searchString)
{
return "<h3> From [HttpPost]Index: " + searchString + "</h3>";
}
然而,使用[HttpPost]的Index方法作為查詢會有一些問題。假如想要將查詢出來的頁面加入至瀏覽器的最愛或是書籤中,或是將網址傳給其他人時,會發現使用[HttpPost]回傳的畫面中,網址列為localhost:xxxxx/Movies/Index,不會帶出查詢的參數,這樣就無法在網址列中分辨出是否篩選了電影,再貼上網址列時只會顯示所有的電影列表。
解決的方法為修改BeginForm方法,在剛剛加入的Html.BeginForm()中加入參數指定發送GET的請求 ,使用HttpGet版本的Index方法。
Html.BeginForm("Index","Movies",FormMethod.Get)
現在點擊查詢時會呼叫[HttpGet] Index方法,而不是[HttpPost] Index方法,網址列也會包含查詢字串searchString。
增加查詢條件
假如在前面有加入[HttpPost] Index方法,請先刪除。
接著,新增一個依照電影的類型(Genre)查詢的功能,修改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與查詢所有電影類型(Genre)的LINQ。
var GenreLst = new List<string>();
var GenreQry = from d in db.Movies
orderby d.Genre
select d.Genre;
AddRange方法將剛剛GenreQry查詢出來的資料( Distinct()方法避免重複的電影類型 )加入GenreLst,再將GenreLst儲存到ViewBag.movieGenre。
而下面的程式碼中,會先檢查movieGenre是否為空或是Null。若有值則加入Where條件,依照Genre篩選電影。
if (!string.IsNullOrEmpty(movieGenre))
{
movies = movies.Where(x => x.Genre == movieGenre);
}
如前面,LINQ查詢會在Index Action方法回傳到View時才執行。
接著,在Index View畫面加入查詢功能。
在Views\Movies\Index.cshtml ,剛剛新增Title查詢的地方,增加一個@Html.DropDownList,如下:
<p>
Genre: @Html.DropDownList("movieGenre", "All")
Title: @Html.TextBox("searchString")
<input type="submit" value="查詢" />
</p>
@Html.DropDownList() 會產生一個下拉式的選單。
參數 "movieGenre" 表示ViewBag.movieGenre,DropDownList 可以依照參數找到ViewBag的IEnumerable<SelectListItem > ,
參數 "All" 會將參數的名稱加入到下拉選單的第一個選項。
ViewBag.movieGenre在MoviesController中的Index Action方法給值:
執行應用程式瀏覽到 /Movies/Index,試著用Gener、Title來查詢電影。
下一篇 資料庫移轉