ASP.NET – MVC – Tìm kiếm sách

Thêm phương thức Search và View tương ứng

Ở giao diện trang Index (http://localhost:xxxx/Book), bạn có thể thấy thiếu một ô tìm kiếm theo tên sách (Title), mô tả liên kết (BookDescription), hay bất cứ trường thuộc tính nào khác. Bây giờ, chúng ta sẽ tiến hành làm điều này.

Cập nhật phương thức Index

Đầu tiên, bạn mở mã nguồn tập tin Controllers/BookController.cs và sửa phương thức Index thành như sau:

 public ActionResult Index (string searchString)
{
    var books = db.Books.Include(b => b.Author).Include(b => b.Category);
    if (!String.IsNullOrEmpty(searchString))
    {
        searchString = searchString.ToLower();
        books = books.Where(b => b.Title.ToLower().Contains(searchString));
    }

    return View(books.ToList());
}

Đoạn mã vừa thay đổi ở phương thức Index hoạt động rất đơn giản như sau. Biến searchString kiểu string là chuỗi tìm kiếm cần nhập vào. Đầu tiên, tạo 1 biến var books để làm câu truy vấn lấy tất cả book từ database, lưu ý kỹ bước này chưa kết nối với database mà chỉ là câu truy vấn. Mệnh đề if kiểm tra nếu biến searchString không null hoặc rỗng (empty) thì thêm điều kiện lọc vào biến books, còn không thì để như ban đầu. Sau đó trả về kết quả, đến đây câu truy vấn mới được hình thành và tương tác với database.

Lấy ví dụ thực tế, nếu bạn có biến searchString có giá trị “Tin” thì chuỗi truy vấn SQL trong biến links được biên dịch từ LINQ sẽ là: “select * from Book where Title like ‘Tin’“. Còn nếu biến searchString không có giá trị thì chuỗi truy vấn sẽ là: “select * from Book“. Cách hoạt động rất đơn giản phải không nào?

Giải thích thêm về đoạn books.Where(b => b.Title.ToLower().Contains(searchString));, mệnh đề Where thì tương tự như mệnh đề where trong ngôn ngữ truy vấn SQL. Phương thức ToLower() đổi tiêu đề sách thành chữ thường, Contains có nghĩa bao hàm, chứa trong. Như vậy, chúng ta tìm các book sao cho có chứa cụm từ là giá trị của biến searchString. OK, tiếp theo bạn thấy cú pháp s => s.Title, đây chính là diễn giải Lambda. Tại sao lại dùng Lambda? Lambda được dùng trong các truy vấn LINQ dựa trên phương thức (như phương thức Where) như là cách đối số để truy vấn các phương thức toán tử để mục đích biểu diễn gọn nhẹ và rút gọn mã nguồn.

Sau khi thêm xong, build dự án (Ctrl + Shift + B), và bạn thử chạy liên kết http://localhost:xxxx/Book trở trình duyệt, mình có thêm 1 số dữ liệu liên kết để demo như sau.

Rồi, sau đó thử chạy lại đường dẫn thêm đoạn truy vấn http://localhost:46418/Book?searchString=tin như sau.

Bạn có thấy, trong URL trên, tôi cố ý để chữ “tin” viết thường mà kết quả vẫn tìm ra các liên kết có tên chữ “Tin” viết hoa chữ T. Độc đáo phải không, suy ra phương thức Contains trong đoạn mã Index cho phép so khớp hoa/thường. Vì vậy, chức năng tìm kiếm với ASP.NET MVC  đơn giản và khỏe hơn bao giờ hết.

Tạo giao diện tìm kiếm ở View

bạn mở tập tin Views\Book\Index.cshtml và sau đoạn  @Html.ActionLink(“Thêm sách mới”, “Create”, null, new { @class = “btn btn-warning” }) bạn thêm đoạn mã:

!-- Đoạn cần thêm -->
@using (Html.BeginForm("Index","Book",FormMethod.Get, new { @class= "form-inline" }))
{
    <div class="form-group">
        <label>Tên sách: </label>
        <input type="Text" class="form-control mx-sm-3"  value="@ViewBag.Keyword" name="searchString" placeholder="Nhập tên sách cần tìm">
        <input type="button" class="btn btn-danger" value="Tìm sách">
    </div><hr/>
}
<!-- Kết thúc -->

Ở đoạn mã trên, chúng ta dùng Html.BeginForm() để tạo 1 phần tử form mặc định dùng HttpPost, với ô tìm kiếm là 1 textbox (@Html.TextBox) và nút nhấn Submit. Đến đây, hãy build dự án (Ctrl + Shift + B) bạn chạy đường dẫn http://localhost:xxxx/Book và nhập vào ô tìm kiếm giá trị “Tin hoc” thì thu được kết quả.

Tìm kiếm theo thể loại (Category)

Như bạn để ý thiết kế database từ đầu, bảng Book có liên kết với bảng Category theo mối quan hệ 1-nhiều. Một Book chỉ thuộc về một Category duy nhất. Đến đây chúng ta cũng tạo Controller cho bảng Category tương tự các bài trước. 

Bây giờ, quay trở lại tập tin Controllers/BookController.cs để sửa phương thức Index như sau.

 public ActionResult Index (string searchString, int categoryID = 0)
{

   // 1. Lưu tư khóa tìm kiếm
    ViewBag.Keyword = searchString;
   //2.Tạo câu truy vấn kết 3 bảng Book, Author, Category
    var books = db.Books.Include(b => b.Author).Include(b => b.Category);
   //3. Tìm kiếm theo searchString
    if (!String.IsNullOrEmpty(searchString))          
        books = books.Where(b => b.Title.Contains(searchString));

    //4. Tìm kiếm theo CategoryID
    if (categoryID != 0)
    {
        books = books.Where(c => c.CategoryID == categoryID);
    }
    //5. Tạo danh sách danh mục để hiển thị ở giao diện View thông qua DropDownList
    ViewBag.CategoryID = new SelectList(db.Categories, "CategoryID", "CategoryName"); // danh sách Category               
    return View(books.ToList());
}

Trong đoạn mã trên, bạn tạo thêm 1 biến categoryID để tìm kiếm theo danh mục. Sau đó ớ (1) lưu từ khóa tìm kiếm, Tiếp, bạn tạo câu truy vấn (2) để kết 3 bảng Auhthor, Book, Category. Mục (3) và (4) kiểm tra dữ liệu, nếu có đầu vào là từ khóa cần tìm và ID danh mục thì thêm vào điều kiện lọc để tìm, ở (4) là tạo danh sách các danh mục, hiển thị danh sách này ở DropDownList bên View Index.cshtml. 

Ở tập tin Views/Book/Index.cshtml, bạn thay đổi nội dung mã nguồn như sau.

<!-- Đoạn cần thêm -->
@using (Html.BeginForm("Index", "Book", FormMethod.Get, new { @class = "form-inline" }))
{
    <div class="form-group">
        <label>Chủ đề:</label>@Html.DropDownList("CategoryID", null, htmlAttributes: new { @class = "form-control" }) <label>Tên sách: </label>
        <input type="Text" class="form-control mx-sm-3" value="@ViewBag.Keyword" name="searchString" placeholder="Nhập tên sách cần tìm">
        <input type="submit" class="btn btn-danger" value="Tìm sách">
    </div><hr />
}
<!-- Kết thúc -->

Kết quả chạy ứng dụng :

Chọn chủ đề “Công nghệ thông tin” và từ khóa “tin học” cho kết quả”: