Ở bài viết trước chúng ta tìm hiểu cách tạo một controller trong ứng dụng ASP.NET MVC, tuy nhiên kết quả trả về của các action chỉ là các chuỗi ký tự đơn giản. Ở bài viết này, chúng ta sẽ học cách để sử dụng các mẫu (.cshtml) để sinh ra mã HTML trả về cho người dùng.
Nếu bạn không quên, thì trong bài trước của loạt bài hướng dẫn này, chúng ta đã tạo controller có tên là HelloWorldController, và bây giờ chúng ta sẽ tạo các view template bằng cách sử dụng Razor View Egine để tạo ra các trang HTML phức tạp và có giao diện như mong muốn của bạn để trả về cho trình duyệt. Razor là một view engine rất thông minh, giúp giảm thiểu số lượng mã lệnh mà bạn cần để tạo ra một mẫu view, và phối hợp nhuần nhuyễn giữa mã ngôn ngữ lập trình (ở đây là C#) và mã đánh dấu HTML.
Đầu tiên bạn hãy điều chỉnh mã của action Index để phương thức này trả về một đối tượng kiểu View như sau:
public ActionResult Index() { return View(); }
Để tạo ra view template bạn có thể dùng cách như sau, nhấp chuột phải lên tên của action (ở đây là Index, và chọn Add View.. như hình dưới đây:
Và sau đó hộp thoại Add View.. sẽ xuất hiện, hãy để mọi thứ như mặc định và nhấn vào nút Add:
Và Visual Studio sẽ tạo cho bạn tập tin Index.cshtml bên trong thư mục ~/Views/HelloWorld, ở hình bên dưới bạn sẽ thấy nội dung của tập tin Index.cshtml phía bên phải.
Và bây giờ bạn sẽ điều chỉnh một chút để có thể nhận ra View đó là của bạn khi trả kết quả về cho trình duyệt. Chúng ta sẽ điều hình Index.cshtml như sau:
@{ ViewBag.Title = "Index"; } <h2>Controller: HelloWorld - Action: Index</h2> <p> Lần đầu thao tác với View Template. </p>
Tiếp theo bạn sẽ chạy ứng dụng và duyệt ứng dụng tại địa chỉ http://localhost:xxxx/HelloWorld và bạn sẽ thấy kết quả như bên dưới.
Bạn thấy ngạc nhiên vì trên URL không bao gồm tên của action nhưng server vẫn hiểu là action Index, tuy nhiên, với cấu hình hiện tại action có tên là Index là action mặc định cho các lợi gọi đến Controller mà không quy định action. Chúng ta sẽ tìm hiểu về định tuyến (routing) trong các phần sau. Dù sao, khởi đầu với View như vậy cũng là đủ tốt, mặc dù tới lúc này bạn chỉ gõ những chuỗi văn bản tĩnh mà thôi. Một điều nữa là tiêu đề của trang web là My MVC Application là một cái tên mặc định, chúng ta sẽ thay đổi trong bước tiếp theo.
Thay đổi Views và Layouts
Để thay đổi tiêu đề My MVC Application xuất hiện ở phần đầu của trnag web, chúng ta cần phải thay đổi nội dung ở giao diện chung được áp dụng mặc định cho các view của ứng dụng. Để làm được điều này, bạn hãy đến thư mục /Views/Shared ở cửa sổ Solution Explorer và mở tập tin _Layout.cshtml. Tập tin này được gọi là trang layout và nó sẽ chia sẽ giao diện chung cho các trang khác sử dụng.
Các mẫu giao diện cho phép bạn có thể quy định giao diện HTML chung chong cả website của bạn tại một nơi và áp dụng nó ở nhiều trang khác nhau. Bạn cũng cần lưu ý dòng @RenderBody() gần cuối của tập tin. RenderBody là một nơi khi mà các nội dung của các view được tạo ra sẽ xuất hiện tại vị trí đó.
Bạn hãy thay đổi tiêu đề nằm trong thẻ <h1> từ “My MVC Application” thành “To do App”. Sau đó hãy vào trình duyệt và click thử vào link About, bạn sẽ thấy tiêu đề của trang cũng đã thay đổi theo thay đổi ở trang Layout. Như vậy nếu áp dụng layout, khi bạn thay đổi trang layout, các trang áp dụng nó cũng sẽ thay đổi theo.
Sau khi đổi xong, bạn hãy chử chạy lại ứng dụng và duyệt qua các link khác nhau thì đều thấy tiêu đề của các trang là “To do App”.
Bây giờ chúng ta sẽ thay tiêu đề của trang HelloWorl/Index.
Hãy mở tập tin /Views/HelloWorld/Index.cshtml, bạn sẽ thay đổi nội dung của ViewBag.Title thành “To do list”. Nếu bạn để ý một chút ở trang _Layout.cshtml mà chúng ta vừa thay đổi trước đây, thì chúng ta sẽ thấy có nội dung <title>@ViewBag.Title</title>, vì vậy khi bạn quy định nội dung của ViewBag.Title thì tiêu đề của cửa sổ trình duyệt cũng sẽ thay đổi theo. Đồng thời bạn sẽ điều chỉnh thêm một chút ở thẻ <h2> của /Views/HelloWorld/Index.cshtml như sau:
ViewBag là một đối tượng của .NET, và nó được sử dụng bên trong view cùng với mã HTML, bạn sẽ thấy những ký tự như khối lệnh C# bắt @{ … }, hoặc @<tên biến>, đó là những điểm khác biệt do Razor View Engine mang lại, để giúp bạn có thể dễ dàng sử dụng ngôn ngữ C# một cách thông minh trong các view template.
Và bạn cũng thấy rằng, view template và layout template được kết hợp với nhau để tạo ra một trang web, và do đó đối tượng ViewBag cũng được sử dụng ở _Layout.cshtml. Kết quả là hình bên dưới:
Như vậy, đến đây chúng ta đã thao tác với Views với Controller, nhưng chúng ta chưa làm gì với chữ M (Model) trong mô hình MVC, chúng ta sẽ học cách sử dụng Model trong mục tiếp theo.
Truyền dữ liệu từ Controller đến View
Trước khi chúng ta thao tác với database (Cơ sở dữ liệu) thật sự, chúng ta cần phải học cách truyền dữ liệu cho View từ Controlller trước. Controller là một lớp được xây dựng nhằm xử lý một số truy vấn nào đó từ phía trình duyệt, mỗi action thường dùng để xử lý một truy vấn cụ thể nào đó. Và tại mỗi action, chúng ta có thể chọn một view bất kỳ để trả kết quả về. Vấn đề là, nếu view đó chỉ có nội dung tĩnh, thì có lẽ chúng ta không cần tới mô hình MVC. Để hiển thị được dữ liệu động thì chúng ta cần truyền dữ liệu (Model) và kết hợp với view template để tạo ra trang HTML để trả về cho trình duyệt.
Như vậy, controller có vai trò sinh ra hoặc lấy dữ liệu cần thiết để áp dụng vào view template và tạo ra nội dung trả về cho trình duyệt. View template (các tập tin *.cshtml) không nên có bất kỹ mã logic nào hoặc trực tiếp thao tác với trình duyệt. Thay vào đó, chúng chỉ nên nhận dữ liệu được truyền đến từ controller. Nếu bạn làm khác đi, bạn đã vi phạm mô hình MVC. Một trong những mục tiêu lớn mà các nhà lập trình áp dụng mô hình MVC là để áp dụng nguyên lý SoC (Seperation of Concerns – tách biệt các mối quan tâm) để giúp mã lệnh sạch sẽ và dễ dàng bảo trì hơn.
Giả thử chúng ta muốn action HelloWorld/Index hiển thị danh sách các việc cần làm, chúng ta sẽ tạo ra một mảng các chuỗi là các việc cần làm, và hiển thị nó ở view như sau:
public ActionResult Index() { var tasks = new List<string>() { "Viết bài hướng dẫn lập trình MVC", "Điều chỉnh chức năng comment của Jou Lập trình", "Đọc truyện Don Kihote", "Trả lời email của anbinhtrong" }; ViewBag.Tasks = tasks; return View(); }
Bạn lại thấy xuất hiện đối tượng ViewBag trong mã lệnh bên trên, nó đã xuất hiện ở view, ở layout template, và giờ là ở action. Thực chất, ViewBag là một đối tượng kiểu dynamic (một kiểu dữ liệu động của được giới thiệu ở .NET Framework 4.0), với kiểu này bạn có thể gán bất cứ thuộc tính nào cho nó ví dụ như ViewBag.Title, hoặc ViewBag.Tasks dù nó không được định nghĩa từ trước. Chúng tôi sẽ có bài giới thiệu về kiểu dynamic và C# trong một khóa học khác. Và quan trọng hơn cả, ViewBag là đối tượng mặc định được truyền giữa Action và View, nói như vậy có nghĩa là, khi bạn quy định giá trị của ViewBag.Tasks ở action, bạn cũng có thể truy xuất nó ở view.
Giờ bạn hãy mở view tương ứng của action HelloWorld/Index là /Views/HelloWorld/Index.cshtml và cập nhật nó như sau:
@{ ViewBag.Title = "To do list"; } <h2>@ViewBag.Title</h2> <p> <ul> @foreach (var task in ViewBag.Tasks) { <li>@task</li> } </ul> </p>
Lần này thì bạn thấy chúng ta sử dụng câu lệnh foreach của C# ngay bên trong view, và nếu bạn tinh ý, thì mỗi lần bạn muốn viết một câu lệnh C# hoặc sử hiển thị giá trị của một biến C# thì bạn đều sử dụng dấu @ phía trước nó. Và điều thần kỳ ở đây, là bạn hoàn toàn có thể truy xuất thuộc tính Tasks của ViewBag, duyệt nó và hiển thị từng đối tượng trong danh sách này bằng thẻ <ul> và <li>.
Hãy biên dịch lại ứng dụng và duyệt địa chỉ /HelloWorld/Index, bạn sẽ thấy kết quả như sau:
Thật tuyệt vời, vì những dữ liệu bạn tạo ra ở Controller đã xuất hiện ở kết quả trả về cho người dùng. Và bạn đã chạm nhẹ vào chữ M (model) trong mô hình MVC. Chúng ta sẽ thao tác nhiều hơn với Model và truy xuất vào database để lấy dữ liệu trong bài viết tiếp theo.