ASP.NET Core 中文文檔 第二章 指南(4.7)添加搜索

来源:http://www.cnblogs.com/dotNETCoreSG/archive/2016/06/19/aspnetcore-2_4_7-search.html
-Advertisement-
Play Games

原文: "Adding Search" 作者: "Rick Anderson" 翻譯: "魏美娟(初見)" 校對: "謝煬(Kiler)" 、 "孟帥洋(書緣)" 、 "張仁建(第二年.夏)" 在本節中,你可以為 方法添加查詢功能,使其能夠根據電影的 genre 或 name 進行查找。 更新 方法 ...


原文:Adding Search
作者:Rick Anderson
翻譯:魏美娟(初見)
校對:謝煬(Kiler) 、孟帥洋(書緣)張仁建(第二年.夏)

在本節中,你可以為 Index 方法添加查詢功能,使其能夠根據電影的 genrename 進行查找。

更新 Index 方法來開啟搜索功能:

public async Task<IActionResult> Index(string searchString)
{
    var movies = from m in _context.Movie
                 select m;

    if (!String.IsNullOrEmpty(searchString))
    {
        movies = movies.Where(s => s.Title.Contains(searchString));
    }

    return View(await movies.ToListAsync());
}

Index 方法的第一行代碼創建了一個LINQ查詢,用來查找符合條件的電影:

var movies = from m in _context.Movie
             select m;

這個查詢 僅僅只是 在這裡被定義出來,但是 並未 在資料庫中執行。

如果 searchString 參數包含一個字元串,movies 查詢將會添加對應查詢過濾條件( 譯者註 本例為 Title 包含 searchString 查詢條件),代碼如下:

if (!String.IsNullOrEmpty(searchString))
{
    movies = movies.Where(s => s.Title.Contains(searchString)); //手工高亮
}

代碼中的 s => s.Title.Contains() 是一個Lambda 表達式,Lambda 表達式被用在基於方法的LINQ查詢(例如:上面代碼中的Where方法 或者 Contains)中當做參數來使用。LINQ 語句在定義或調用類似 WhereContains 或者 OrderBy 的方法進行修改的時候不會執行,相反的,查詢會延遲執行,這意味著一個賦值語句直到迭代完成或調用 ToListAsync 方法才具備真正的值。更多關於延時查詢的信息。請參考 查詢執行

註意
Contains方法是在資料庫中運行的,並非在上面的 C# 代碼中。在資料庫中,Contains方法被翻譯為不區分大小寫的SQL LIKE腳本。

運行應用程式,並導航到 /Movies/Index,在 URL 後面添加一個查詢字元串,例如 ?searchString=ghost,被過濾後的電影列表如下:

search/_static/ghost.png

如果你修改 Index 方法簽名使得方法包含一個名為 id 的參數,那麼 id 參數將會匹配 Startup.cs 文件中的預設路由中的可選項 {id} 。

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}"); //手工高亮
});

你可以使用 rename 操作快速的把 searchString 參數重命名為 id,在 searchString 上右擊 > Rename

search/_static/rename.png

會被重命名的代碼會高亮顯示。

search/_static/rename2.png

修改參數為 id ,其他引用到 searchString 的地方也會自動變更為 id

search/_static/rename3.png

修改前的 Index 方法:

public async Task<IActionResult> Index(string searchString) //手工高亮
{
    var movies = from m in _context.Movie
                 select m;

    if (!String.IsNullOrEmpty(searchString)) //手工高亮
    {
        movies = movies.Where(s => s.Title.Contains(searchString)); //手工高亮
    }

    return View(await movies.ToListAsync());
}

修改後的 Index 方法:

public async Task<IActionResult> Index(string id) //手工高亮
{
    var movies = from m in _context.Movie
                 select m;

    if (!String.IsNullOrEmpty(id)) //手工高亮
    {
        movies = movies.Where(s => s.Title.Contains(id)); //手工高亮
    }

    return View(await movies.ToListAsync());
}

修改完成以後,我們可以通過路由數據(URL 區塊)來傳遞標題搜索條件而非查詢字元串:

search/_static/g2.png

然而,你不能指望用戶每次都通過修改URL來查找電影,因此你需要在界面上幫助他們過濾數據。如果你想要修改 Index 方法的簽名並測試了路由綁定是如何傳遞 ID 參數,現在再把它改成原來的參數 searchString

public async Task<IActionResult> Index(string searchString) //手工高亮
{
    var movies = from m in _context.Movie
                 select m;

    if (!String.IsNullOrEmpty(searchString)) //手工高亮
    {
        movies = movies.Where(s => s.Title.Contains(searchString)); //手工高亮
    }

    return View(await movies.ToListAsync());
}
@model IEnumerable<MvcMovie.Models.Movie>

@{
    ViewData["Title"] = "Index";
}

<h2>Index</h2>

<p>
    <a asp-action="Create">Create New</a>
</p>

<!--下麵的整個form標簽高亮-->
<form asp-controller="Movies" asp-action="Index">
    <p>
        Title: <input type="text" name="SearchString"> 
        <input type="submit" value="Filter" />
    </p>
</form>

<table class="table">
    <thead>

HTML <form> 標簽使用Form Tag Helper生成,所以當你提交表單的時候,過濾字元串都被傳到了 movies 控制器的 Index 方法。保存你的修改並測試過濾。

search/_static/filter.png

然而 Index 方法並沒有你所希望的 [HttpPost] 重載。你也不需要,因為方法並不會修改應用程式的狀態,僅僅只是過濾數據。

你可以添加下麵的 [HttpPost] Index 方法。

[HttpPost] //手工高亮
public string Index(string searchString, bool notUsed)
{
    return "From [HttpPost]Index: filter on " + searchString;
}

notUsed 參數用創建 Index 方法重載。我們在後續教程中會討論。

如果你添加了這個方法。action 會調用匹配 [HttpPost] Index 的方法, [HttpPost] Index 方法運行結果如下所示。

search/_static/fo.png

然而,儘管添加了 [HttpPost] 版的 Index 方法,在實現的時候仍然存在一些局限性。設想你想將一個比較詳細的查詢添加書簽,或者你想將查詢結果以鏈接形式發送給朋友以便於你的朋友可以看到同樣的過濾結果的電影,註意觀察 HTTP POST 請求的時候,URL 是沒有改變的(仍然是 localhost:xxxxx/Movies/Index),這個地址本身不包含查詢信息。現在,查詢信息是作為表單數據發送到伺服器的,你可以通過 F12 開發者工具或者優秀的抓包工具 Fiddler tool。啟動F12 開發者工具

選擇 http://localhost:xxx/Movies HTTP POST 200 行點擊 Body > Request Body

search/_static/f12_rb.png

你可以在請求正文中看到查詢參數和上一個教程中提到的XSRF令牌。Form Tag Helper生成XSRF 反偽造令牌。我們沒有修改數據,所以無需在控制器方法中驗證令牌。

因為查詢參數在請求正文中而不是 Url 里,所以你在書簽裡面無法保存查詢參數並共用給他人,為瞭解決這個問題,我們必須把請求指定為 HTTP GET。註意智能感知將幫我們更新標簽。

search/_static/int_m.png

search/_static/int_get.png

請註意, <form> 標簽中的專有標記。這種專有標記表示的標簽是由Tag Helpers 支持的。

search/_static/th_font.png

當你提交檢索的時候,URL 包含查詢條件,如果存在 HttpPost Index 方法,查詢會跳轉到 HttpGet Index 方法。

search/_static/search_get.png

添加按照 Genre 查詢

Models 目錄添加下麵的 MovieGenreViewModel 類:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace MvcMovie.Models
{
    public class MovieGenreViewModel
    {
        public List<Movie> movies;
        public SelectList genres;
        public string movieGenre { get; set; }
    }
}

move-genre 視圖模型包含:

  • 電影列表
  • 包含 genre 列表的SelectList。允許用戶從列表中選擇 genre 。
  • movieGenre,包含選中的 genre

用下麵的代碼替換 Index 方法:

public async Task<IActionResult> Index(string movieGenre, string searchString)
{
    IQueryable<string> genreQuery = from m in _context.Movie
                                    orderby m.Genre
                                    select m.Genre;

    var movies = from m in _context.Movie
                 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);
    }

    var movieGenreVM = new MovieGenreViewModel();
    movieGenreVM.genres = new SelectList(await genreQuery.Distinct().ToListAsync());
    movieGenreVM.movies = await movies.ToListAsync();

    return View(movieGenreVM);
}

下麵代碼是通過 LINQ 語句從資料庫中檢索所有 genre 數據。

IQueryable<string> genreQuery = from m in _context.Movie
                                orderby m.Genre
                                select m.Genre;

SelectList 的 genres 通過 Distinct 方法投影查詢創建(我們不想選擇列表中出現重覆的數據)。

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

在 Index 視圖中添加通過 genre 檢索

<!--手工高亮-->
@model MovieGenreViewModel
@{
    ViewData["Title"] = "Index";
}

<h2>Index</h2>
<p>
    <a asp-action="Create">Create New</a>
</p>

<form asp-controller="Movies" asp-action="Index" method="get">
    <p>
        <select asp-for="movieGenre" asp-items="Model.genres"> <!--手工高亮-->
            <option value="">All</option> <!--手工高亮-->
        </select> <!--手工高亮-->

        Title: <input type="text" name="SearchString">
        <input type="submit" value="Filter" />
    </p>
</form>

<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor( model => model.movies[0].Genre ) <!--手工高亮-->
        </th>
        <th>
            @Html.DisplayNameFor( model => model.movies[0].Price )
        </th>
        <th>
            @Html.DisplayNameFor( model => model.movies[0].ReleaseDate )
        </th>
        <th>
            @Html.DisplayNameFor( model => model.movies[0].Title )
        </th>
        <th></th>
    </tr>
    <tbody>
        @foreach( var item in Model.movies ) //手工高亮
        {
            <tr>
                <td>
                    @Html.DisplayFor( modelItem => item.Genre )
                </td>
                <td>
                    @Html.DisplayFor( modelItem => item.Price )
                </td>
                <td>
                    @Html.DisplayFor( modelItem => item.ReleaseDate )
                </td>
                <td>
                    @Html.DisplayFor( modelItem => item.Title )
                </td>
                <td>
                    <a asp-action="Edit" asp-route-id="@item.ID">Edit</a> |
                    <a asp-action="Details" asp-route-id="@item.ID">Details</a> |
                    <a asp-action="Delete" asp-route-id="@item.ID">Delete</a>
                </td>
            </tr>
        }
    </tbody>
</table>

測試程式並分別通過 genre 或者 電影標題以及兩個條件同時進行檢索

返回目錄


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 今天是我第一天開通博客,也是我的第一篇博客。以後為大家帶來第一篇關於學習技術性文章,這段時間會為大家帶來是SQL入門學習。希望大家堅持讀下去,因為學歷有限。我也是初學者。語言表達能力不好和知識點不足,我寫的不好,希望大家多多包涵。主要分享給那些想學SQL一個入門教程。主要是T-SQL語言為主。學完這 ...
  • ...
  • 本實例代碼實現了WinForm截屏保存為圖片,親測可行。界面截圖:下載:http://hovertree.com/h/bjaf/scjyuanma.htm以下代碼可以實際運行,在項目HoverTreeCSJ中運行成功。 轉自:http://hovertree.com/h/bjaf/76q5yeli. ...
  • 繼承、Overriding重寫、動態綁定、Sealed密封類、Object類、重載==和!= ...
  • svcutil.exe http://localhost:9065/ServiceDemo.svc?wsdl這將生成一個配置文件和一個包含客戶端類的代碼文件。 下麵我們就用這個是怎麼生成的:1,打開Visual Studio命令提示(Visual Studio Tools下麵)2,在打開的界面裡面輸 ...
  • WebClient位於System.Net命名空間下,通過這個類可以方便的創建Http請求並獲取返回內容。 一、用法1 - DownloadData 二、用法2 - OpenRead 推薦:http://www.cnblogs.com/roucheng/p/3521864.html ...
  • 很久沒有寫博客了。 這是放暑假中的第一篇博客,以後會多多更新!!! 這就是我寫的一個字體選擇器,界面如下: 本程式用到的技術比較簡單,僅僅是用了Font類的幾個方法和數據綁定而已。 首先建一個四行兩列的Grid,添加一個ComboBox,命名為fonts。然後在添加若幹個TextBlock和一個Te ...
  • 前幾天一個同事跑過來找我說,我們在廣告素材視頻這塊想做斷點續傳,就是這次某個視頻緩存到一半,下次不用重頭開始,可以在原來停留得位置開始繼續下載.以提供更好的用戶體驗。 同時說需要我們支持吐素材地址的業務介面告訴終端最後修改時間/文件簽名(md5),用這個用來判斷我當前要下的文件有沒有變化,同時告訴終 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...