【譯】MVC3 20個秘方-(9)在結果中篩選
問題
當排序和分頁都不夠幫用戶去找到他們想要的結果時,另外一種幫助用戶找到他們想要的結果的方式是根據特殊的規則過濾。
解決方案
添加新的links 允許使用預先的條件去過濾并且使用LINQ類庫去在數據中過濾。
討論
為了添加過濾的鏈接,需要在Book/Index view 和BookController中做改變。
改變的View和前兩個秘方差不多。需要添加HTML去允許用戶去選擇他們想如何過濾內容。三個連接將被添加:全部的,新發布的和即將到來的。新發布的將被定義為最近2周發布的。即將到來的就被定義為還沒發布的。
下邊是新的 Book/Index view。有三個link。第一個link包含當前的sortOrder,剩下的2個link包含了新的變量filter。像分頁link一樣。如果當前的filter是你選中的話,把他顯示成靜態文本而不是link,其他的fitler設置為link的形式。確保用戶更改排序規則時,filter也被維護。我們的Index view 要更新成如下:
@Html.Partial("_Paging")
<table>
<tr>
<th>
@Html.ActionLink("Title", "Index", new
{
sortOrder = ViewBag.TitleSortParam,
filter = ViewBag.CurrentFilter
})
</th>
<th>
@Html.ActionLink("Isbn", "Index", new
{
sortOrder = ViewBag.IsbnSortParam,
filter = ViewBag.CurrentFilter
})
</th>
<th>
Summary
</th>
<th>
@Html.ActionLink("Author", "Index", new
{
sortOrder = ViewBag.AuthorSortParam,
filter = ViewBag.CurrentFilter
})
</th>
<th>
Thumbnail
</th>
<th>
@Html.ActionLink("Price", "Index", new
{
sortOrder = ViewBag.PriceSortParam,
filter = ViewBag.CurrentFilter
})
</th>
<th>
@Html.ActionLink("Published", "Index", new
{
sortOrder = ViewBag.PublishedSortParam,
filter = ViewBag.CurrentFilter
})
</th>
<th>
</th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.Isbn)
</td>
<td>
@Html.DisplayFor(modelItem => item.Summary)
</td>
<td>
@Html.DisplayFor(modelItem => item.Author)
</td>
<td>
@Html.DisplayFor(modelItem => item.Thumbnail)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.DisplayFor(modelItem => item.Published)
</td>
<td>
@Html.ActionLink("Edit","Edit", new { id = item.ID }) |
@Html.ActionLink("Details","Details", new { id = item.ID }) |
@Html.ActionLink("Delete","Delete", new { id = item.ID })
</td>
</tr>
}
</table>
@Html.Partial("_Paging")
上一個秘方中創建的_Paging的Partial view也需要被更新。在下邊的例子里,4個paging link 已經被更新成傳遞了當前的filter,page,和sortOrder。以下是_Paging更新后的代碼:
<p>
@if (Model.HasPreviousPage)
{
@Html.ActionLink("<< First", "Index", new
{
page = 1,
sortOrder = ViewBag.CurrentSortOrder,
filter = ViewBag.CurrentFilter
})
@Html.Raw(" ");
@Html.ActionLink("< Prev", "Index", new
{
page = Model.PageNumber - 1,
sortOrder = ViewBag.CurrentSortOrder,
filter = ViewBag.CurrentFilter
})
}
else
{
@:<< First
@Html.Raw(" ");
@:< Prev
}
@if (Model.HasNextPage)
{
@Html.ActionLink("Next >", "Index", new
{
page = Model.PageNumber + 1,
sortOrder = ViewBag.CurrentSortOrder,
filter = ViewBag.CurrentFilter
})
@Html.Raw(" ");
@Html.ActionLink("Last >>", "Index", new
{
page = Model.PageCount,
sortOrder = ViewBag.CurrentSortOrder,
filter = ViewBag.CurrentFilter
})
}
else
{
@:Next >
@Html.Raw(" ")
@:Last >>
}
</p>
接下來我們要改變BooksController,在Index()Action 中更改代碼。新接收一個filter變量。圖書的列表將基于用戶選擇的filter選項被縮減。有2中方法實現filter。
- 再次使用動態Linq庫 的where子句。
- 使用標準的Linq 和一個switch塊去創建一個強類型的子句。
由于傳統的filter link并不包含太多的條目,這個秘方,我們選擇用第二種實現方法。這樣做的好處是,我們不需要考慮SQL注入的問題,因為他是強類型的,并且不是動態的。
以下是BooksController部分代碼:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Linq.Dynamic;
using System.Web;
using System.Web.Mvc;
using MvcApplication.Models;
using MvcApplication.Utils;
using PagedList;
namespace MvcApplication.Controllers
{
public class BooksController : Controller
{
private BookDBContext db = new BookDBContext();
//
// GET: /Books/
public ViewResult Index(string sortOrder,string filter, int page = 1)
{
#region ViewBag Resources
#endregion
#region ViewBag Sort Params
#endregion
var books = from b in db.Books select b;
#region Filter Switch
switch (filter)
{
case "NewReleases":
var startDate = DateTime.Today.AddDays(-14);
books = books.Where(b => b.Published
<= DateTime.Today.Date
&& b.Published >= startDate
);
break;
case "ComingSoon":
books = books.Where(b => b.Published >
DateTime.Today.Date);
break;
default:
// No filter needed
break;
}
ViewBag.CurrentFilter =
String.IsNullOrEmpty(filter) ? "" : filter;
#endregion
books = books.OrderBy(sortOrder);
const int maxRecords = 2;
var currentPage = page <= 0 ? 1 : page;
return View(books.ToPagedList(currentPage,maxRecords));
}
}
}
在上邊的例子里,如果用戶選擇NewReleases 這個filter,這個搜索將返回今天或者14天之內出版的書。或者用戶選擇了Coming soon,搜索將返回即將出版的書。

浙公網安備 33010602011771號