[ASP.NET MVC] 新增查詢功能

[ASP.NET MVC] 在Index新增查詢功能,依照電影名稱與類型查詢電影。

修改Index Form

首先,先修改MoviesControllerIndex 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.movieGenreMoviesController中的Index Action方法給值:

執行應用程式瀏覽到 /Movies/Index,試著用Gener、Title來查詢電影。

 

下一篇  資料庫移轉

 

 END 

回目錄