Thứ Năm, 6 tháng 9, 2018

Sử dụng View Components trong ASP.NET Core

Partial Views and Child Actions là một trong những tính năng được sử dụng nhiều nhất trong ASP.NET MVC. Partial Views cung cấp cho chúng ta cách tạo thành phần có thể sử dụng lại trong nhiều Views. Có những action có thể được đánh dấu là [ChildAction] (hành động con) và những action này không thể được gọi thông qua URL mà chỉ được gọi bên trong view hoặc partial view. Child Actions không có sẵn trong ASP.NET Core. Thay vào đó chúng ta phải sử dụng View Components để thay thế. View Component hỗ trợ trong cả ASP.NET Core MVCRazor Pages.

Những hạn chế của Partial Views


Partial View có những thách thức và hạn chế nhất định. Nếu chúng ta sử dụng child action trong một view thì trong khi thực thi, một vòng đời bổ sung sẽ diễn ra, vòng đời ASP.Net MVC đầu tiên thực hiện cho việc nạp view chính và một khi nó được nạp xong thì một vòng đời nữa lại thực hiện xử lý child action. Ngoài ra, nếu đặt bộ lọc (filter) nhất định như bộ lọc ủy quyền [Authorize] trên child action và sử dụng child action này trong Layout View thì có thể làm cho trang không thể tải hoàn tất nếu ủy quyền không thành công (tức child action ảnh hướng đến toàn bộ view). Nó cũng không hỗ trợ lập trình async, khả năng kiểm tra, tách mối quan tâm (Separation of Concerns ), ... 

View Component là gì? 


View Component là một trong nhiều tính năng tuyệt vời được giới thiệu trong ASP.NET Core. View Component thực chất cũng tương tự như Partial View, cho phép chúng ta tái sử dụng trong nhiều view. Tuy nhiên nó mạnh hơn rất nhiều Partial View vì những cải thiện và sửa đổi từ ASP.NET Core tiêu biểu là hỗ trợ lập trình đồng bộ (async programming), khả năng kiểm thử và bảo trì dễ dàng hơn, Dependency Injection friendly, separation of concerns (phân tách xử lỷ nghiệp vụ và giao diện).

Ví dụ về LoginViewComponent


Tạo 1 View component


Bước 1: Tạo class với tên phải có đuôi cuối là ViewComponent và phải kế thừa class ViewComponent. Ví dụ:

1
2
3
4
5
6
7
public class MenuViewComponent : ViewComponent
{
}


Bước 2: Tạo method InvokeAsync() trả về kiểu Task<IViewComponentResult>Method có thể nhiều hoặc không có tham số. Các tham số này được chuyền từ view hoặc razor page sang. Ví dụ sau mình tạo 1 MenuViewComponent lấy danh sách phân loại sản phẩm và truyền qua view thông qua lệnh return View().

public class MenuViewComponent: ViewComponent
    {
        private readonly OnlineStoreDbContext db;
        public MenuViewComponent(OnlineStoreDbContext db)
        {
            this.db = db;
        }
        public async Task<IViewComponentResult> InvokeAsync()
        {
            return View(await db.Categories.OrderBy(m => m.Order).ToListAsync());
        }
    }

Bước 3: Tạo file giao diện. Đối với view component có 1 điều bạn đặc biệt lưu ý là tên thư mục tạo để chứa giao diện của view component là phải chính xác theo tên của class bạn đặt. Ví dụ nếu mình muốn dùng menu cho nhiều trang thì mình cần tạo cấu trúc thư mục Components/Menu đặt trong thư mục Shared với tên file sẽ là Default.cshtml. Ví dụ như hình.








Cú pháp trong file Default.cshtml thì giống như các file partial view trước đây. Ví dụ đoạn code của mình như sau:


Bước 4: Sau khi tạo class và tạo view xong thì bạn cần gọi sử dụng view component trong layout hoặc bất cứ view nào khác. Cú pháp gọi như sau:
 @await Component.InvokeAsync("Name of view component",
<các tham số truyền vào view component nếu có>)

Ví dụ trong Layout view mình muốn gọi MenuViewComponent thì cú pháp như sau: @await  Component.InvokeAsync("Menu"). 






Vì method InvokeAsync mình tạo trước đó không có tham số thì lúc gọi không cần truyền thêm tham số gì.

Đây là kết quả đạt được. Chúc bạn thực hành thành công và áp dụng tốt vào dự án ASP.NET Core thực tế.