011.Adding Search to an ASP.NET Core MVC app –【给程序添加搜索功能】

Adding Search to an ASP.NET Core MVC app

深受程序添加搜索效果

2017-3-7 7 分钟阅读时长 作者 

正文内容

1.Adding Search by
genre

根据音乐流派添加搜索

2.Adding search by genre to the Index
view

于 Index
视图添加音乐流派搜索效果

By Rick Anderson

In this section you add search capability to the Index action method
that lets you search movies by genre or name.

当本节咱们将于 Index
方法添加搜索功能,可以找音乐流派或音乐之讳。

Update the Index method with the following code:

故底的代码更新 Index
方法:

图片 1图片 2

 1 public async Task<IActionResult> Index(string searchString)
 2 
 3 {
 4 
 5     var movies = from m in _context.Movie
 6 
 7                  select m;
 8 
 9  
10 
11     if (!String.IsNullOrEmpty(searchString))
12 
13     {
14 
15         movies = movies.Where(s => s.Title.Contains(searchString));
16 
17     }
18 
19  
20 
21     return View(await movies.ToListAsync());
22 
23 }

C# code

The first line of the Index action method creates
a LINQ query to
select the movies:

Index 方法的率先执写了一个
LINQ
查询表达式,以询问有movie数据:

图片 3图片 4

1 var movies = from m in _context.Movie
2 
3              select m;

C# code

The query is only defined at this point, it has not been run
against the database.

夫查询表达式仅仅以这儿定义了,他是惰性的,不会见朝数据库请求执行。

If the searchString parameter contains a string, the movies query is
modified to filter on the value of the search string:

searchString
参数包含了一个字符串,movie查询会失去因这个搜索字符串过滤查询数据:

图片 5图片 6

1 if (!String.IsNullOrEmpty(id))
2 
3 {
4 
5     movies = movies.Where(s => s.Title.Contains(id));
6 
7 }

C# code

The s => s.Title.Contains() code above is a Lambda
Expression.

上面的 s =>
s.Title.Contains() 是 Lambda 表达式。

Lambdas are used in
method-based LINQqueries
as arguments to standard query operator methods such as
the Where method
or Contains (used in the code above).

Lambda
表达式被用于因函数为参数的正式操作函数,如: Where
方法要地方的 Contains 方法。

LINQ queries are not executed when they are defined or when they are
modified by calling a method such as Where, Contains or OrderBy.

LINQ
查询表达式在概念之早晚不会见尽,当他们吃 Where, Contains or OrderBy
修改时也非会见履行。

Rather, query execution is deferred.

查询的实践是为推的,它是惰性执行的。

That means that the evaluation of an expression is delayed until its
realized value is actually iterated over or the ToListAsyncmethod is
called.

意乃是,表达式的求值会让推迟到真正的失遍历或者调用了ToListAsync
方法,才见面起算计表达式的价值。

For more information about deferred query execution, see Query
Execution.

查看 Query
Execution
以获取更多关于表达式延迟执行之音。

Note:
The Contains method
is run on the database, not in the c# code shown above.

笔记: Contains
方法会被翻译啊sql并于DB中施行,而无是当C#遇调用执行。

The case sensitivity on the query depends on the database and the
collation.

询问表达式是恃让聚集或者DB对象的。

On SQL
Server, Contains maps
to SQL LIKE, which is
case insensitive.

在 SQL Server 上,Contains
方法会被智能的炫耀为 SQL
LIKE 。

In SQLlite, with the default collation, it’s case sensitive.

当 SQLlite
中,他会晤智能的默认矫正。

Navigate to /Movies/Index.

每当地点栏导航及 /Movies/Index

Append a query string such as ?searchString=Ghost to the URL.

在URL后长一段落像
?searchString=Ghost 的询问字符串。

The filtered movies are displayed.

过滤后的movie数据就是显出来了。

图片 7

If you change the signature of the Index method to have a parameter
named id,

比方你更改 Index
的章程签名,使该参数名字吧 id ,

the id parameter will match the optional {id} placeholder for the
default routes set in Startup.cs.

id 参数将会默认匹配
Startup.cs 文件中的 {id} 可卜参数的占有位符。

图片 8图片 9

 1 app.UseMvc(routes =>
 2 
 3 {
 4 
 5     routes.MapRoute(
 6 
 7         name: "default",
 8 
 9         template: "{controller=Home}/{action=Index}/{id?}");
10 
11 });

C# code

You can quickly rename the searchString parameter to id with
the rename command.

若得以 rename
命令快速的重命名 searchString 参数为 id 。

Right click on searchString > Rename.

右击,并选择 > Rename
菜单。

图片 10

The rename targets are highlighted.

亟待还命名的靶子将会晤漫高亮显示,如下:

图片 11 

Change the parameter to id and all occurrences of searchString change
to id.

改变参数名也 id
,下面有出现的 searchString 都见面让命名也 id 。

 图片 12

The previous Index method:

前面的 Index
方法,如下:

图片 13图片 14

 1 public async Task<IActionResult> Index(string searchString)
 2 
 3 {
 4 
 5     var movies = from m in _context.Movie
 6 
 7                  select m;
 8 
 9  
10 
11     if (!String.IsNullOrEmpty(searchString))
12 
13     {
14 
15         movies = movies.Where(s => s.Title.Contains(searchString));
16 
17     }
18 
19  
20 
21     return View(await movies.ToListAsync());
22 
23 }

C# code

The updated Index method with id parameter:

更新后的 Index 方法以带有名为
id  的参数,如下:

图片 15图片 16

 1 public async Task<IActionResult> Index(string id)
 2 
 3 {
 4 
 5     var movies = from m in _context.Movie
 6 
 7                  select m;
 8 
 9  
10 
11     if (!String.IsNullOrEmpty(id))
12 
13     {
14 
15         movies = movies.Where(s => s.Title.Contains(id));
16 
17     }
18 
19  
20 
21     return View(await movies.ToListAsync());
22 
23 }

C# code

You can now pass the search title as route data (a URL segment) instead
of as a query string value.

卿现在便得将追寻标题的字符串做吧总长由于数据的等同有些要休是一个询问字符串使用了。

图片 17 

However, you can’t expect users to modify the URL every time they want
to search for a movie.

唯独,你无见面希望用户每次去更改URL,当她们搜寻他们顾念要之录像的当儿。

So now you’ll add UI to help them filter movies.

为此,你需要增加UI来协助他们过滤想如果之movies。

If you changed the signature of the Index method to test how to pass the
route-bound ID parameter, change it back so that it takes a parameter
named searchString:

若你改变了 Index
方法的签名来测试路由于数据绑定,现在拿他转移回去,如下:

图片 18图片 19

 1 public async Task<IActionResult> Index(string searchString)
 2 
 3 {
 4 
 5     var movies = from m in _context.Movie
 6 
 7                  select m;
 8 
 9  
10 
11     if (!String.IsNullOrEmpty(searchString))
12 
13     {
14 
15         movies = movies.Where(s => s.Title.Contains(searchString));
16 
17     }
18 
19  
20 
21     return View(await movies.ToListAsync());
22 
23 }

C# code

Open the Views/Movies/Index.cshtml file, and add
the <form> markup highlighted below:

打开
Views/Movies/Index.cshtml 文件,并且增长 <form>
标签,如下面高亮部分所示:

图片 20图片 21

 1     ViewData["Title"] = "Index";
 2 
 3 }
 4 
 5  
 6 
 7 <h2>Index</h2>
 8 
 9  
10 
11 <p>
12 
13     <a asp-action="Create">Create New</a>
14 
15 </p>
16 
17  
18 
19 <form asp-controller="Movies" asp-action="Index">
20 
21     <p>
22 
23         Title: <input type="text" name="SearchString">
24 
25         <input type="submit" value="Filter" />
26 
27     </p>
28 
29 </form>
30 
31  
32 
33 <table class="table">
34 
35     <thead>

HTML Code

The HTML <form> tag uses the Form Tag
Helper,
so when you submit the form, the filter string is posted to
the Index action of the movies controller.

<form> 标签下了 Form Tag
Helper
,因此当你付表单时,过滤字符串被付至了Index  方法。

Save your changes and then test the filter.

封存你的改,然后测试搜索效果。

图片 22 

There’s no [HttpPost] overload of the Index method as you might
expect.

刚而你所预期,在 Index 方法齐没有
[HttpPost] 特征标记类。

You don’t need it, because the method isn’t changing the state of the
app, just filtering data.

卿免需他,因为此艺术不见面改变应用之然和状态,仅仅是查询了一些数据。

You could add the following [HttpPost] Index method.

您呢得以填补加 [HttpPost]
,如下的 Index 方法:

图片 23图片 24

1 [HttpPost]
2 
3 public string Index(string searchString, bool notUsed)
4 
5 {
6 
7     return "From [HttpPost]Index: filter on " + searchString;
8 
9 }

C# code

The notUsed parameter is used to create an overload for
the Index method.

notUsed
参数为用来创造了一个重载的 Index 方法。

We’ll talk about that later in the tutorial.

我们以于末端的课被对其进行讲解。

If you add this method, the action invoker would match the [HttpPost]
Index method, and the [HttpPost] Index method would run as shown in
the image below.

万一您长这个艺术,action
调用器将见面配合配 [HttpPost] Index 方法,并且 [HttpPost] Index
将会见实施并返如下图所著信息:

图片 25 

However, even if you add this [HttpPost] version of the Index method,
there’s a limitation in how this has all been implemented.

只是,即使你补充加了 [HttpPost]
版本的 Index 方法,这也起局部限制,就是公如怎么来贯彻。

Imagine that you want to bookmark a particular search or you want to
send a link to friends that they can click in order to see the same
filtered list of movies.

怀疑你想标记一些缕的索,或者您想叫心上人发送一个老是,这个连续可以于他俩看到和而同一的movies检索结果。

Notice that the URL for the HTTP POST request is the same as the URL for
the GET request (localhost:xxxxx/Movies/Index) — there’s no search
information in the URL.

瞩目到 HTTP POST
请求的URL与GET请求的URL完全相同,在URL上没有找字符串的多少。

The search string information is sent to the server as a form field
value.

摸索用底字符串被做啊表单字段达到的价传递让服务器。

You can verify that with the browser Developer tools or the
excellent Fiddler tool.

而可据此浏览器开发者工具来验证。

The image below shows the Chrome browser Developer tools:

生图展示了 Chrome
浏览器的开发者工具:

图片 26 

You can see the search parameter
and XSRF token
in the request body.

乃可于请求体中看出 搜索参数
与 XSRF
令牌。

Note, as mentioned in the previous tutorial, the Form Tag
Helper generates
an XSRF anti-forgery
token.

顾,如前方边儿教程提到的均等,是
Form Tag
Helper
生成了 XSRF
防伪造令牌。

We’re not modifying data, so we don’t need to validate the token in the
controller method.

俺们不去修改数据,因此呢未待以控制器中证明令牌。

Because the search parameter is in the request body and not the URL, you
can’t capture that search information to bookmark or share with others.

盖查询参数在求求体中,而未是当URL中,所以您无法捕获查询信息补充加书签或享受给其他人。

We’ll fix this by specifying the request should be HTTP GET.

咱们修复这点仅需要指定要形式也 HTTP
GET 即可。

Notice how intelliSense helps us update the markup.

小心vs的智能感知如何援助我们创新html标记。

 图片 27

图片 28 

Notice the distinctive font in the <form> tag.

瞩目在 <form>
标签中的绝不的字颜色。

That distinctive font indicates the tag is supported by Tag
Helpers.

不同的字体颜色指明了什么样受
Tag
Helpers
支持。

图片 29 

Now when you submit a search, the URL contains the search query string.

现,当您付出一个询问的时刻,URL中即在查询字符串中含有了询问参数。

Searching will also go to the HttpGet Index action method, even if you
have a HttpPost Index method.

查询将会晤一直调用 HttpGet Index
,即使就存在了一个 HttpPost Index 方法。

图片 30 

The following markup shows the change to the form tag:

下面的符号展示了 form
标签的反:

图片 31图片 32

1 <form asp-controller="Movies" asp-action="Index" method="get">

HTML Code

Adding Search by genre

加上冲门进行检索的效力

Add the following MovieGenreViewModel class to the Models folder:

Models 文件夹下加加
MovieGenreViewModel 类:

图片 33图片 34

 1 using Microsoft.AspNetCore.Mvc.Rendering;
 2 
 3 using System.Collections.Generic;
 4 
 5  
 6 
 7 namespace MvcMovie.Models
 8 
 9 {
10 
11     public class MovieGenreViewModel
12 
13     {
14 
15         public List<Movie> movies;
16 
17         public SelectList genres;
18 
19         public string movieGenre { get; set; }
20 
21     }
22 
23 }

C# Code

The movie-genre view model will contain:

movie-genre 视图将富含:

  • A list of movies.

一个影视列表。

  • A SelectList containing the list of genres. This will allow the user
    to select a genre from the list.

SelectList
将包含一文山会海流派,这将如用户可于内部选择流派。

  • movieGenre, which contains the selected genre.

movieGenre
,它富含了吃捎的派。

Replace the Index method in MoviesController.cs with the following code:

用下的代码替换到
MoviesController.cs 文件中之 Index 方法中:

图片 35图片 36

 1 // Requires using Microsoft.AspNetCore.Mvc.Rendering;
 2 
 3 public async Task<IActionResult> Index(string movieGenre, string searchString)
 4 
 5 {
 6 
 7     // Use LINQ to get list of genres.
 8 
 9     IQueryable<string> genreQuery = from m in _context.Movie
10 
11                                     orderby m.Genre
12 
13                                     select m.Genre;
14 
15  
16 
17     var movies = from m in _context.Movie
18 
19                  select m;
20 
21  
22 
23     if (!String.IsNullOrEmpty(searchString))
24 
25     {
26 
27         movies = movies.Where(s => s.Title.Contains(searchString));
28 
29     }
30 
31  
32 
33     if (!String.IsNullOrEmpty(movieGenre))
34 
35     {
36 
37         movies = movies.Where(x => x.Genre == movieGenre);
38 
39     }
40 
41  
42 
43     var movieGenreVM = new MovieGenreViewModel();
44 
45     movieGenreVM.genres = new SelectList(await genreQuery.Distinct().ToListAsync());
46 
47     movieGenreVM.movies = await movies.ToListAsync();
48 
49  
50 
51     return View(movieGenreVM);
52 
53 }

C# Code

The following code is a LINQ query that retrieves all the genres from
the database.

下是一个 LINQ
查询,他找了数据库被的装有派别:

图片 37图片 38

1 // Use LINQ to get list of genres.
2 
3 IQueryable<string> genreQuery = from m in _context.Movie
4 
5                                 orderby m.Genre
6 
7                                 select m.Genre;

C# Code

The SelectList of genres is created by projecting the distinct genres
(we don’t want our select list to have duplicate genres).

SelectList
由工程创建并就此来让家去重新:

图片 39图片 40

1 movieGenreVM.genres = new SelectList(await genreQuery.Distinct().ToListAsync())

C# Code

Adding search by genre to the Index view

将家查询添加到 Index
视图上

Update Index.cshtml as follows:

于是脚代码 更新 Index.cshtml
文件:

图片 41图片 42

  1 @model MvcMovie.Models.MovieGenreViewModel
  2 
  3  
  4 
  5 @{
  6 
  7     ViewData["Title"] = "Index";
  8 
  9 }
 10 
 11  
 12 
 13 <h2>Index</h2>
 14 
 15  
 16 
 17 <p>
 18 
 19     <a asp-action="Create">Create New</a>
 20 
 21 </p>
 22 
 23  
 24 
 25 <form asp-controller="Movies" asp-action="Index" method="get">
 26 
 27     <p>
 28 
 29         <select asp-for="movieGenre" asp-items="Model.genres">
 30 
 31             <option value="">All</option>
 32 
 33         </select>
 34 
 35  
 36 
 37         Title: <input type="text" name="SearchString">
 38 
 39         <input type="submit" value="Filter" />
 40 
 41     </p>
 42 
 43 </form>
 44 
 45  
 46 
 47 <table class="table">
 48 
 49     <thead>
 50 
 51         <tr>
 52 
 53             <th>
 54 
 55                 @Html.DisplayNameFor(model => model.movies[0].Title)
 56 
 57             </th>
 58 
 59             <th>
 60 
 61                 @Html.DisplayNameFor(model => model.movies[0].ReleaseDate)
 62 
 63             </th>
 64 
 65             <th>
 66 
 67                 @Html.DisplayNameFor(model => model.movies[0].Genre)
 68 
 69             </th>
 70 
 71             <th>
 72 
 73                 @Html.DisplayNameFor(model => model.movies[0].Price)
 74 
 75             </th>
 76 
 77             <th></th>
 78 
 79         </tr>
 80 
 81     </thead>
 82 
 83     <tbody>
 84 
 85         @foreach (var item in Model.movies)
 86 
 87         {
 88 
 89             <tr>
 90 
 91                 <td>
 92 
 93                     @Html.DisplayFor(modelItem => item.Title)
 94 
 95                 </td>
 96 
 97                 <td>
 98 
 99                     @Html.DisplayFor(modelItem => item.ReleaseDate)
100 
101                 </td>
102 
103                 <td>
104 
105                     @Html.DisplayFor(modelItem => item.Genre)
106 
107                 </td>
108 
109                 <td>
110 
111                     @Html.DisplayFor(modelItem => item.Price)
112 
113                 </td>
114 
115                 <td>
116 
117                     <a asp-action="Edit" asp-route-id="@item.ID">Edit</a> |
118 
119                     <a asp-action="Details" asp-route-id="@item.ID">Details</a> |
120 
121                     <a asp-action="Delete" asp-route-id="@item.ID">Delete</a>
122 
123                 </td>
124 
125             </tr>
126 
127         }
128 
129     </tbody>
130 
131 </table>

HTML Code

Examine the lambda expression used in the following HTML Helper:

反省下html中使的 lambda
表达式:

图片 43图片 44

1 @Html.DisplayNameFor(model => model.movies[0].Title)

HTML Code

In the preceding code, the DisplayNameFor HTML Helper inspects
the Title property referenced in the lambda expression to determine the
display name.

在上面的代码中,DisplayNameFor
html帮助器函数检查 Title 属性,并操纵其的界面及之展示名。

Since the lambda expression is inspected rather than evaluated, you
don’t receive an access violation when model, model.movies,
or model.movies[0] are null or empty.

当 lambda
去反省如果不是去算时,你无欲接受或者 model, model.movies,
or model.movies[0] are null or empty 。

When the lambda expression is evaluated (for
example, @Html.DisplayFor(modelItem => item.Title)), the model’s
property values are evaluated.

当 lambda
计算时(例如:@Html.DisplayFor(modelItem =>
item.Title)),模型的属于性值是吃计算的。

Test the app by searching by genre, by movie title, and by both.

经过寻找流派或找标题来测试照程序。

 

 

                                         蒙

                                    2017-08-21
16:18 周一

 

相关文章