问题
当排序和分页和过滤都不够帮用户去找到他们想要的结果时,想一个最好的备选方式是让用户输入(关键字)他们想要什么。
解决方案
用HtmlHelper创建一个新的From和 文本输入框,并且借助LINQ根据用户输入的关键字在之前过滤过的结果里查找。
讨论
和前边的秘方很像,添加一个根据keyword 搜索的功能需要更新 Book/Index view 和 BookController。在View里添加一个新的from和textbox 让用户输入keyword。同时也要确保当用户改变排序规则、过滤、分页时,关键字保持。
下边的代码是对View的更新:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
@model PagedList.IPagedList< MvcApplication.Models.Book > < h2 >@MvcApplication4.Resources.Resource1.BookIndexTitle</ h2 > < p > @Html.ActionLink("Create New", "Create") </ p > < p > Show: @if (ViewBag.CurrentFilter != "") { @Html.ActionLink("All", "Index", new { sortOrder = ViewBag.CurrentSortOrder, Keyword = ViewBag.CurrentKeyword }) } else { @:All } | @if (ViewBag.CurrentFilter != "NewReleases") { @Html.ActionLink("New Releases", "Index", new { filter = "NewReleases", sortOrder = ViewBag.CurrentSortOrder, Keyword = ViewBag.CurrentKeyword }) } else { @:New Releases } | @if (ViewBag.CurrentFilter != "ComingSoon") { @Html.ActionLink("Coming Soon", "Index", new { filter = "ComingSoon", sortOrder = ViewBag.CurrentSortOrder, Keyword = ViewBag.CurrentKeyword }) } else { @:Coming Soon } </ p > @using (Html.BeginForm()) { @:Search: @Html.TextBox("Keyword")< input type = "submit" value = "Search" /> } @Html.Partial("_Paging") < table > < tr > < th > @Html.ActionLink("Title", "Index", new { sortOrder = ViewBag.TitleSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }) </ th > < th > @Html.ActionLink("Isbn", "Index", new { sortOrder = ViewBag.IsbnSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }) </ th > < th > Summary </ th > < th > @Html.ActionLink("Author", "Index", new { sortOrder = ViewBag.AuthorSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }) </ th > < th > Thumbnail </ th > < th > @Html.ActionLink("Price", "Index", new { sortOrder = ViewBag.PriceSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }) </ th > < th > @Html.ActionLink("Published", "Index", new { sortOrder = ViewBag.PublishedSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }) </ 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") |
最终,BookController 需要被更新,在下边的例子,Index() action 更新
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
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,string Keyword, int page = 1) { #region ViewBag Resources #endregion #region ViewBag Sort Params #endregion var books = from b in db.Books select b; #region Keyword Search if (!String.IsNullOrEmpty(Keyword)) { books = books.Where(b => b.Title.ToUpper().Contains(Keyword.ToUpper()) || b.Author.ToUpper().Contains( Keyword.ToUpper())); } ViewBag.CurrentKeyword = String.IsNullOrEmpty(Keyword) ? "" : Keyword; #endregion #region Filter Switch #endregion int maxRecords = 1; int currentPage = page - 1; return View(books.ToPagedList(currentPage, maxRecords)); } } } |
译者:上边代码是以书名和作者名为搜索条件的。你也可以自己扩展。比如根据ISBN:
1
2
3
4
5
|
books = books.Where(b => b.Title.ToUpper().Contains(Keyword.ToUpper()) || b.Author.ToUpper().Contains( Keyword.ToUpper()||b.ISBN.ToUpper().Contains( Keyword.ToUpper())); |
当然这样做的话查询效率会有问题。我们可以在UI提供一个dropdownlist 让用户去选择根据什么条件去搜索关键字。