

Các Phương thức hành động (Action Methods) và khái niệm nâng cao trong C# MVC
- 24-02-2025
- Toanngo92
- 0 Comments
Mục lục
Phương Thức Hành Động trong MVC
Các phương thức hành động trong ASP.NET xử lý yêu cầu và tạo ra phản hồi tương ứng. Thông thường, phản hồi được tạo dưới dạng ActionResult. Các hành động thường được ánh xạ trực tiếp với tương tác người dùng. Ví dụ, mở trình duyệt web và nhập URL. Khi URL mở ra, bạn có thể nhấp vào bất kỳ liên kết nào trên trang đó và gửi nó. Bất cứ khi nào xảy ra tương tác như vậy, nó gửi yêu cầu đến máy chủ chứa dữ liệu được sử dụng bởi framework MVC để gọi một phương thức hành động.
Các nhà phát triển có thể hiểu cách hoạt động của phương thức hành động bằng cách xem xét URL mẫu sau: http://localhost:7575/PersonDetail/Index
Trong URL này, có thể nhận thấy rằng PersonDetail là controller và Index là phương thức hành động. Khi người dùng nhập URL này trong trình duyệt, họ đang gọi phương thức hành động Index. Bảng 6.1 liệt kê các thành phần của phương thức hành động:
Các Thành Phần Phương Thức Hành Động
URL | Controller | Action |
---|---|---|
/PersonDetail/Index | PersonDetail | Index |
Một cách đơn giản, trình duyệt gửi một yêu cầu đến controller, sau đó gọi phương thức. Nếu phương thức không thể được tìm thấy trong controller, một ngoại lệ HttpNotFound sẽ được trả về.
Controller với Phương Thức Hành Động trong ASP.NET MVC
Các phương thức hành động luôn trả về các kết quả khác nhau. Trong ASP.NET, một phương thức có kiểu trả về ActionResult được gọi là một phương thức hành động. Khi nhà phát triển tạo ứng dụng MVC và một controller được tự động tạo, lớp controller sẽ có một hoặc nhiều phương thức hành động.
Ví dụ mã (Code Snippet 1):
using Demo.Models;
namespace Demo.Controllers {
public class MemberDetailsController : Controller {
// GET: MemberDetails
[HttpGet]
public ActionResult Index() {
return View();
}
}
}
ASP.NET MVC ActionResult
ActionResult biểu thị kết quả của các phương thức hành động hoặc loại kết quả trả về của các phương thức hành động được mô tả trong System.Web.Mvc namespace. ActionResult là một lớp trừu tượng, được sử dụng như một lớp cơ sở cho nhiều loại kết quả hành động khác nhau.
Giá trị trả về của một phương thức hành động là một view, được dẫn xuất từ lớp cơ sở ViewResult. Một kiểu trả về ActionResult tùy chỉnh có thể được phát triển bằng cách tạo một lớp kế thừa từ lớp trừu tượng ActionResult.
Các Loại ActionResult được Hỗ Trợ bởi ASP.NET MVC
Action Result | Helper Method | Description |
---|---|---|
ViewResult | View | Hiển thị một view và truyền dữ liệu. |
PartialViewResult | PartialView | Hiển thị một phần view. |
RedirectToRouteResult | RedirectToRoute | Chuyển hướng đến một route cụ thể. |
ContentResult | Content | Trả về nội dung tùy chỉnh. |
HttpNotFoundResult | HttpNotFound | Trả về thông báo tài nguyên không tìm thấy. |
FileResult | File | Trả dữ liệu nhị phân cho đầu ra. |
FileStreamResult | Controller.File(Stream, String) hoặc Controller.File(Stream, String, String) | Giao tiếp nội dung nhị phân với phản hồi thông qua stream. |
FileContentResult | Controller.File(Byte[], String) hoặc Controller.File(Byte[], String, String) | Giao tiếp nội dung tệp nhị phân với phản hồi. |
EmptyResult | (None) | Hiển thị giá trị trả về nếu action method trả về kết quả là giá trị null (void). |
So sánh giữa Web API và SOAP
Có hai loại giao thức giao tiếp chính trong dịch vụ web, gồm:
- Giao thức Truy cập Đối tượng Đơn giản (SOAP).
- Truyền Trạng thái Đại diện (REST).
Mặc dù SOAP đã được sử dụng trong các giao diện dịch vụ web như một giao thức tiêu chuẩn trong thời gian dài, nhưng gần đây, nó đã dần bị REST thay thế.
REST hoặc Dịch vụ RESTful
Thuật ngữ REST (Representational State Transfer) ám chỉ một khái niệm kiến trúc hỗ trợ phát triển các dịch vụ web đơn giản, giúp truy cập và sửa đổi tài nguyên web thông qua URL.
Roy Fielding đã giới thiệu REST, sau đó nó được sử dụng rộng rãi trong ngành công nghiệp phần mềm. REST xác định rằng mỗi tài nguyên cần có một định danh duy nhất (URI). Ví dụ: http://www.website.com/student?id=10
Ví dụ này truy cập thông tin của sinh viên với ID là 10 và trả về dữ liệu dưới dạng các định dạng như XML, HTML hoặc JSON.
Ví dụ SOAP (Code Snippet 2):
<soap:Body xmlns="http://www.yoursite.org/student">
<em:GetStudent>
<em:StudentId>101</em:StudentId>
</em:GetStudent>
</soap:Body>
Trong đoạn mã trên, dịch vụ SOAP trả về một thông điệp chứa thông tin sinh viên.
Ví dụ REST (Code Snippet 3):
<soap:Body xmlns="http://www.yoursite.org/student">
<em:GetStudentResponse>
<em:StudentId>101</em:StudentId>
<em:Name>Tom Alexa</em:Name>
<em:Email>tom.alexa@gmail.com</em:Email>
<em:DateOfJoin>12-Jun-2017</em:DateOfJoin>
</em:GetStudentResponse>
</soap:Body>
Phân tích HTTP Status Code:
- 200: Trả về nếu tài nguyên tồn tại.
- 201: Tạo thành công tài nguyên mới.
- 404: Tài nguyên được yêu cầu không tìm thấy.
Ví dụ REST (Code Snippet 4 – Request):
GET /student/101 HTTP/1.1
Host: www.website.com
Accept: application/vnd.student+json
Ví dụ REST (Code Snippet 5 – Response):
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"data": {
"StudentId": "101",
"Name": "Tom Alexa",
"Email": "tom.alexa@gmail.com",
"DateOfJoin": "12-Jun-2017"
}
}
Các ví dụ trên chứng minh rằng REST nhẹ hơn SOAP nhờ việc loại bỏ XML phức tạp. REST sử dụng các HTTP status codes một cách phù hợp để mô tả trạng thái của tài nguyên và cung cấp liên kết đến các tài nguyên liên quan.
Kiến trúc REST và Web API
Kiến trúc REST tuân theo nguyên tắc “Hypermedia As The Engine Of Application State” (HATEOAS), hoạt động với client để xác định nội dung cần trả về trong định dạng mà client có thể hiểu.
Nhờ hỗ trợ HTTP, dịch vụ REST cung cấp các dịch vụ web hiệu quả bằng cách sử dụng hypermedia để xử lý kết nối client-server.
Tạo Dịch vụ RESTful trong ASP.NET
Dịch vụ RESTful có thể được xây dựng bằng cách sử dụng framework ASP.NET Web API. Giống như trong MVC, ASP.NET Web API cũng có các tính năng như:
- Bộ lọc hành động,
- Bộ điều khiển (controller),
- Ràng buộc mô hình (model binding),
- Hợp lệ hóa dữ liệu (model validation),
- Và các tính năng khác.
Web API cũng được gọi là HTTP API hoặc REST API trong một số trường hợp. Trong kiến trúc REST, một API không có hỗ trợ hypermedia không được coi là hoàn toàn RESTful. ASP.NET Web API cung cấp khả năng tạo REST API và khuyến khích sử dụng mô hình lập trình HTTP để xây dựng các dịch vụ web nhẹ, phù hợp với nhiều client.
So sánh REST và SOAP
Bảng 6.3: So sánh REST và SOAP
REST | SOAP |
---|---|
Hoạt động thông qua nhiều giao diện khác nhau để truy cập tài nguyên. | Hoạt động thông qua các giao diện ứng dụng. |
REST tiết lộ các thành phần của ứng dụng dưới dạng dịch vụ. | SOAP tiết lộ các thành phần ứng dụng dưới dạng dữ liệu. |
REST cung cấp cách dễ dàng hơn để truy cập dịch vụ web bằng HTTP. | SOAP sử dụng giao thức nhắn tin có cấu trúc phức tạp. |
REST nhẹ và dễ sử dụng hơn so với SOAP. | SOAP ban đầu được phát triển bởi Microsoft và đã được sử dụng rộng rãi. |
Lợi ích của REST so với SOAP
Dưới đây là những lợi ích của REST khi so sánh với SOAP:
- REST hỗ trợ nhiều định dạng dữ liệu khác nhau, trong khi SOAP chỉ hỗ trợ XML. Các dịch vụ web dựa trên trình duyệt như eBay, Google, Amazon và Yahoo thường ưu tiên REST làm giao thức ưa thích.
- Về hiệu suất, REST có lợi thế hơn SOAP nhờ vào kỹ thuật bộ nhớ đệm (caching) để lưu trữ thông tin tạm thời không thể chỉnh sửa. REST nhanh hơn và dễ sử dụng hơn so với SOAP.
- Các trang web hiện tại có thể được sử dụng mà không cần cấu trúc lại cơ sở hạ tầng dữ liệu. Điều này cho phép các nhà phát triển thêm chức năng mới và tiết kiệm thời gian bằng cách không phải thiết kế lại toàn bộ từ đầu. Mặc dù REST có nhiều lợi ích hơn SOAP, vẫn có một số trường hợp sử dụng SOAP là giải pháp được khuyến nghị.
Lợi ích của SOAP so với REST
Dưới đây là những lợi ích của SOAP khiến nó trở thành giao thức được ưu tiên hơn REST trong một số trường hợp:
- Mặc dù REST là giao thức được sử dụng phổ biến nhất, nhưng đôi khi SOAP vượt trội hơn REST về mặt chức năng. SOAP được sử dụng khi cần các ứng dụng bảo mật cao, đặc biệt khi có yêu cầu về bảo mật WS-Security. SOAP hỗ trợ xác minh danh tính, cung cấp tính riêng tư dữ liệu, và kiểm tra các kết nối bị lỗi mà REST không có.
- SOAP được thiết kế với giao thức HTTP, giúp dễ dàng làm việc với các tường lửa và các cơ chế bảo mật khác mà không cần thay đổi giao thức cơ bản. SOAP cũng hỗ trợ các giao dịch tuân thủ ACID với độ tin cậy giao dịch cao, điều mà REST không hỗ trợ.
- SOAP thường được sử dụng trong các ứng dụng yêu cầu mã hóa phức tạp, đòi hỏi các hoạt động cần duy trì trạng thái và bảo mật ở tầng ứng dụng. Nó tương thích với các công nghệ khác như WS-ReliableMessaging, WS-Coordination và WS-Security.
- Các tổ chức lựa chọn giao thức dựa trên yêu cầu của khách hàng mà họ đang hỗ trợ. REST và JSON chủ yếu được sử dụng vì tiêu tốn ít băng thông hơn, dễ hiểu và dễ triển khai hơn đối với các nhà phát triển.
Lựa chọn giữa REST và SOAP
Nếu cần phải chọn giữa REST và SOAP, các khía cạnh sau đây sẽ giúp đưa ra quyết định dựa trên yêu cầu:
- Dịch vụ web SOAP thực hiện hoạt động POST mọi lúc. Ngược lại, REST cung cấp tùy chọn để chọn các phương thức HTTP khác nhau, chẳng hạn như POST, DELETE, GET, và PUT.
- SOAP cung cấp bảo mật và độ tin cậy tốt hơn cho các ứng dụng.
- REST dễ triển khai hơn vì có mã nhẹ hơn, trong khi SOAP hữu ích khi API thay đổi liên tục và phức tạp.
Do đó, có thể kết luận rằng REST và SOAP có chức năng hoàn toàn khác nhau và hoạt động tốt trong các tình huống khác nhau. Các hoạt động dựa trên web thường sử dụng REST và SOAP để quản lý các đối tượng từ xa. REST được thiết kế dựa trên HTTP, tận dụng các thao tác cơ bản như GET, DELETE, và POST, giúp REST chiếm ưu thế hơn so với SOAP trong nhiều ứng dụng API công cộng.
Ngược lại, SOAP sử dụng XML và có các tính năng cho phép xác định các kết nối giữa người dùng và nhà cung cấp. Tuy nhiên, SOAP tiêu thụ băng thông nhiều hơn so với REST.
Khai báo Route Config
Routing được định nghĩa là một cách tiếp cận “dò mẫu” (pattern matching) theo dõi các yêu cầu và quyết định nơi gửi chúng để xử lý. Nó cố gắng khớp mẫu URL của yêu cầu với mẫu có sẵn trong bảng Route.
Quy trình Routing hoạt động như sau:
- Tìm kiếm (Search),
- So khớp (Match),
- Điều hướng (Forward).
Nếu không tìm thấy khớp trong bảng Route cho URL nhận được, nó hiển thị lỗi HTTP 404. Điều quan trọng là các tên Route phải duy nhất trong toàn bộ ứng dụng.
Ví dụ mã (Code Snippet 6):
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Mặc định Route có thể được thay đổi và được chỉ định trong RouteConfig khi tạo một dự án. RouteConfig.cs về cơ bản cung cấp cách định nghĩa các quy tắc điều hướng URL trong ứng dụng.
RouteConfig trong ASP.NET MVC
Khi cần định nghĩa các route khác nhau cho các trường hợp sử dụng, RouteConfig là yếu tố được sử dụng. Để hiểu khi nào cần điều chỉnh route, hãy xem xét ví dụ về một trang web: /Blog/Post/1234/my-blog-post
, nơi có không gian dành riêng cho các bài đăng trên blog và cần được sửa đổi để phù hợp.
Quy tắc định tuyến
RouteConfig tuân theo các tiêu chuẩn chung và được đặt tiền tố bởi khu vực (area) với định dạng: /{area}/{controller}/{action}/{id}
Ví dụ đoạn mã (Code Snippet 7):
context.MapRoute(
"Blog",
"Blog/Post/{id}/{name}",
new { action = "Index", controller = "Post", new_id = @"\d+" }
);
URL này sẽ cho phép truy cập đường dẫn như: ~/blog/posts/123/Food
.
Ví dụ đoạn mã (Code Snippet 8):
public class RouteConfig {
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
Đoạn mã trên hiển thị cách định nghĩa cấu hình Route mặc định.
Khởi tạo Route trong global.asax.cs
Đoạn mã dưới đây minh họa cách gọi RegisterRoutes
trong global.asax.cs
:
protected void Application_Start() {
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
Sử dụng các lớp cấu hình
Các lớp cấu hình như:
- RouteConfig.cs
- WebApiConfig.cs
- AuthConfig.cs
- BundleConfig.cs
- FilterConfig.cs
Gói (Bundling) và Giảm Thiểu/nén (Minification) trong MVC
Hiệu suất của một trang web đóng vai trò quan trọng trong quá trình phát triển. Do đó, việc cải thiện tốc độ tải trang và đồng thời sử dụng ít tài nguyên máy chủ hơn là rất cần thiết. Để đạt được điều này, từ phiên bản ASP.NET 4.5 trở đi, đã cung cấp các tính năng tích hợp gọi là bundling (gói) và minification (giảm thiểu).
Gói (Bundling)
Khi người dùng truy cập vào một trang web từ bất kỳ trình duyệt nào, nhiều yêu cầu (requests) được gửi tới máy chủ, ví dụ như CSS, JavaScript, và jQuery. Điều này dẫn đến nhiều phản hồi (responses). Để khắc phục vấn đề này, từ ASP.NET 4.5.1 trở đi, tính năng gói cho phép gom nhóm logic các tệp thành một gói với một tên duy nhất. Sau đó, gói này chỉ được tải thông qua một yêu cầu HTTP duy nhất. Gói có thể được tạo cho cả tệp JavaScript và CSS.
Giảm Thiểu (Minification)
Giảm thiểu là quá trình xóa các ký tự thừa như khoảng trắng, dòng trống, và các dòng chú thích (comments) khỏi mã nguồn, làm giảm kích thước tệp. Cách tiếp cận này giúp cải thiện thời gian tải của mã nguồn.
Vai trò của Gói và Giảm Thiểu
- Tăng hiệu suất: Giảm số lượng yêu cầu gửi đến máy chủ.
- Giảm kích thước tệp tải: Các tệp JavaScript và CSS nhỏ hơn giúp tải nhanh hơn.
- Loại bỏ ký tự thừa: Chẳng hạn, khoảng trắng và chú thích không cần thiết trong mã.
Kỹ thuật giảm thiểu khi áp dụng cho tệp JavaScript hoặc CSS sẽ giảm kích thước và làm gọn các biến thành một ký tự duy nhất.
Ví dụ Đoạn mã JavaScript (Code Snippet 10):
function myFunction(x) {
var text;
// Nếu x không phải là số hoặc nhỏ hơn 1 hoặc lớn hơn 10
if (isNaN(x) || x < 1 || x > 10) {
text = "Input not valid";
} else {
text = "Input OK";
}
document.getElementById("message").innerHTML = text;
}
Phiên bản đã được tối ưu hóa và giảm thiểu của đoạn mã trên sẽ được hiển thị trong Code Snippet 11.
Code Snippet 11:
var t;
isNaN(n) || n < 1 || n > 10 ? (t = "Input not valid") : (t = "Input OK"),
document.getElementById("message").innerHTML = t;
Mô tả:
- Đoạn mã trên minh họa cách loại bỏ khoảng trắng và chú thích không cần thiết.
- Các biến được nén để giảm kích thước tệp JavaScript.
- Việc sử dụng bundling và minification làm giảm thời gian tải trang bằng cách giảm kích thước tệp và số lượng yêu cầu HTTP.
Các lớp Bundle hỗ trợ trong MVC
Các lớp bundle trong ASP.NET MVC (phiên bản 5 trở lên) thuộc System.Web.Optimization bao gồm:
- ScriptBundle: Dùng để gom nhóm và giảm thiểu các tệp JavaScript.
- StyleBundle: Dùng để gom nhóm và giảm thiểu các tệp CSS.
- DynamicFolderBundle: Được ASP.NET tạo động cho các tệp cùng loại.
ScriptBundle
Lớp ScriptBundle trong ASP.NET MVC API thực hiện việc gói (bundling) và giảm thiểu (minification) các tệp JavaScript. Các bước thực hiện:
Bước 1: Tạo file cấu hình
Đi tới App_Start/BundleConfig.cs. Tệp này do ASP.NET MVC quản lý.
Ví dụ đoạn mã (Code Snippet 12):
using System.Web;
using System.Web.Optimization;
public class BundleConfig {
public static void RegisterBundles(BundleCollection bundles) {
// Tạo đối tượng ScriptBundle và chỉ định tên gói
ScriptBundle spBundle = new ScriptBundle("~/bundles/bootstrap");
spBundle.Include(
"~/Scripts/bootstrap.js",
"~/Scripts/respond.js"
);
// Thêm bundle vào bộ sưu tập
bundles.Add(spBundle);
// Kích hoạt tối ưu hóa bundle
BundleTable.EnableOptimizations = true;
}
}
Mô tả:
- Tạo một đối tượng ScriptBundle bằng cách truyền tên gói (virtual path) dưới dạng tham số.
- Thêm các tệp JavaScript vào bundle bằng phương thức Include().
- Thêm bundle vào bộ sưu tập BundleCollection.
- Kích hoạt tối ưu hóa bằng cách đặt BundleTable.EnableOptimizations = true.
Sử dụng IncludeDirectory
Một cách khác để gom nhóm tất cả các tệp trong một thư mục là sử dụng phương thức IncludeDirectory(), cho phép tự động thêm tất cả các tệp trong một thư mục cụ thể vào bundle. Chi tiết được minh họa trong Code Snippet 13.
Code Snippet 13: Sử dụng IncludeDirectory
public static void RegisterBundles(BundleCollection bundles) {
bundles.Add(new ScriptBundle("~/bundles/JsScripts")
.IncludeDirectory("~/JsScripts", "*.js", true));
}
Giải thích:
- IncludeDirectory: Phương thức này cho phép bao gồm tất cả các tệp trong một thư mục cụ thể (ở đây là
~/JsScripts
) và chỉ định kiểu tệp, chẳng hạn như*.js
. - Đoạn mã này được gọi khi ứng dụng bắt đầu thông qua phương thức
RegisterBundles
được định nghĩa trong lớpBundleConfig
.
Code Snippet 14: Tích hợp Bundles trong ứng dụng
public class Global : HttpApplication {
protected void Application_Start() {
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
Giải thích:
- Trong sự kiện
Application_Start
, các gói (bundles) được đăng ký bằng cách gọi phương thứcRegisterBundles
.
Sử dụng Wildcards
Khi tên của các tệp script bao gồm cả phiên bản (version) do bên thứ ba cung cấp, việc nâng cấp phiên bản có thể gây phiền phức nếu phải thay đổi mã nguồn. Để giải quyết, bạn có thể sử dụng wildcards:
- Wildcards tự động bao gồm phiên bản phù hợp của tệp khi được chỉ định.
Ví dụ minh họa:
- Câu lệnh jQuery có thể chỉ định phiên bản trong tên tệp, và khi sử dụng ký tự đại diện (
*
), câu lệnh sẽ tự động chọn phiên bản tương ứng có sẵn.
Code Snippet 15: Sử dụng Wildcards
public class BundleConfig {
public static void RegisterBundles(BundleCollection bundles) {
bundles.Add(new ScriptBundle("~/bundles/jquery")
.Include("~/Scripts/jquery-{version}.js"));
}
}
Giải thích:
{version}
: Là wildcard cho phép bao gồm phiên bản phù hợp của tệp. Ví dụ:- Nếu phiên bản hiện tại là 1.7.1, thì đoạn mã trên sẽ chọn tệp
jquery-1.7.1.js
. - Khi có phiên bản nâng cấp (ví dụ:
jquery-1.10.2.js
), đoạn mã này vẫn chọn phiên bản mới mà không cần thay đổi mã nguồn hoặc biên dịch lại.
- Nếu phiên bản hiện tại là 1.7.1, thì đoạn mã trên sẽ chọn tệp
Sử dụng Mạng Phân Phối Nội Dung (CDN)
CDN hỗ trợ tải các tệp script. Thư viện jQuery có thể được tải từ CDN. Code Snippet 16 dưới đây minh họa cách triển khai tự động.
Code Snippet 16:
public class BundleConfig {
public static void RegisterBundles(BundleCollection bundles) {
var cdnPath = "http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.7.1.min.js";
bundles.Add(new ScriptBundle("~/bundles/jquery", cdnPath)
.Include("~/Scripts/jquery-{version}.js"));
}
}
Giải thích:
- Trong Release mode, jQuery sẽ được tải từ CDN.
- Trong Debug mode, thư viện jQuery sẽ được tải từ nguồn cục bộ.
- Để tránh lỗi khi yêu cầu CDN không thành công, bạn nên có cơ chế dự phòng (alternative mechanism).
Tích hợp ScriptBundle vào Razor View
Để sử dụng ScriptBundle trong Razor View, cần thực hiện các bước sau:
- Bao gồm các Bundle trong Razor View:
- Các bundle phải được tích hợp bằng cách sử dụng lớp static scripts class.
- Sử dụng phương thức Scripts.Render():
- Phương thức này giúp thêm các script bundle cụ thể vào thời gian chạy (runtime).
Code Snippet 17:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewBag.Title</title>
@Styles.Render("~/Content/css")
@Styles.Render("~/Content/bootstrap")
</head>
<body>
<!-- Nội dung HTML sẽ hiển thị tại đây -->
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
</body>
</html>
Giải thích Code Snippet 17:
- Styles.Render: Được sử dụng để tải các tệp CSS bundle, như
bootstrap.css
. - Scripts.Render: Được sử dụng để tải các tệp JavaScript bundle, như
jquery
vàbootstrap.js
.
Khi Code Snippet 17 được thực thi, hai tệp script sẽ được gói (bundled), giảm thiểu (minified), và tải dưới dạng một yêu cầu duy nhất. Debug mode cần được đặt thành OFF
như sau:
<compilation debug="false" targetFramework="5.0" />
StyleBundle
Các bước thực hiện StyleBundle tương tự như ScriptBundle. Phương pháp thêm đường dẫn ảo (virtual path) và tên tệp/mẫu (patterns) trong ScriptBundle cũng được áp dụng cho StyleBundle.
Code Snippet 18: Cấu hình StyleBundle và ScriptBundle
public class BundleConfig {
public static void RegisterBundles(BundleCollection bundles) {
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate.js"));
// Sử dụng phiên bản phát triển của Modernizr trong giai đoạn phát triển.
// Khi sẵn sàng sản xuất, hãy sử dụng công cụ build để tối ưu hóa mã Modernizr.
bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
"~/Scripts/modernizr-*"));
bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
"~/Scripts/bootstrap.js",
"~/Scripts/respond.js"));
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/site.css"));
bundles.Add(new StyleBundle("~/Content/bootstrap").Include(
"~/Content/bootstrap.css"));
}
}
Giải thích:
- ScriptBundle:
- Tích hợp các tệp JavaScript như
jquery-{version}.js
,jquery.validate.js
, vàmodernizr-*
. - Dành cho các tệp script như
bootstrap.js
vàrespond.js
.
- Tích hợp các tệp JavaScript như
- StyleBundle:
- Gom nhóm các tệp CSS như
site.css
vàbootstrap.css
.
- Gom nhóm các tệp CSS như
Code Snippet 19: Đăng ký Bundle trong Global.asax.cs
using System;
using System.Web;
using System.Web.Optimization;
namespace StudentManagement {
public class Global : HttpApplication {
protected void Application_Start() {
BundleConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
}
Giải thích:
- Trong sự kiện
Application_Start
, phương thứcRegisterBundles
được gọi để đăng ký các bundle vào ứng dụng. - Điều này đảm bảo các bundle được sử dụng khi ứng dụng khởi chạy.
Tích hợp và Sử dụng Bundles trong Các Views
Code Snippet 20:
@using System.Web.Optimization
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/modernizr")
@Styles.Render("~/Content/css")
@Styles.Render("~/Content/themes/base/css")
Giải thích:
- Các bundle như
jquery
vàmodernizr
được tải thông qua phương thức Scripts.Render. - Tương tự, các tệp CSS như
themes/base/css
được tải bằng Styles.Render.
Chú ý trong Chế độ Phát triển (Development Mode):
- Bundling không hoạt động trong chế độ phát triển:
- Điều này xảy ra khi thuộc tính
debug
trong tệpweb.config
được đặt là"true"
. Khi ở chế độ phát triển, các file sẽ không được gói và giảm thiểu.
- Điều này xảy ra khi thuộc tính
- Chế độ sản xuất (Production Mode):
- Khi thuộc tính
debug
được đặt là"false"
, hệ thống sẽ thực hiện bundling các tệp.
- Khi thuộc tính
Điều này có thể gây nhầm lẫn khi các tệp tham chiếu sử dụng đường dẫn tương đối tồn tại trong các tệp khác, ví dụ như tham chiếu đến tệp CSS của Bootstrap.
Sử dụng CSSRewriteUrlTransform
Code Snippet 21:
bundles.Add(new StyleBundle("~/bundles/CSS")
.Include("~/Content/CSS/*.css", new CssRewriteUrlTransform()));
Giải thích:
- Lớp CssRewriteUrlTransform thay thế các đường dẫn URL tương đối trong các tệp bundle bằng các đường dẫn tuyệt đối.
- Điều này đảm bảo rằng các tham chiếu URL vẫn chính xác ngay cả khi vị trí của bundle thay đổi.
Ví dụ:
- Tệp
~/Content/CSS/bootstrap.css
có thể được chuyển thành~/bundles/CSS/bootstrap.css
bằng cách áp dụng triển khai như trong Code Snippet 21.
Tôi sẽ xử lý và dịch nội dung từ ảnh mới nhất này. Đợi một chút nhé!
Dịch nội dung chi tiết sang tiếng Việt:
Giảm thiểu (Minification) và kiểm soát minification trong chế độ debug và release
Giảm thiểu là một quy trình được sử dụng để giảm kích thước các tệp CSS và JavaScript, qua đó giảm thời gian tải xuống. Điều này được thực hiện bằng cách loại bỏ các ký tự thừa như khoảng trắng, chú thích, và nội dung không quan trọng khác từ các tệp.
- Quy trình này sử dụng các đối tượng ScriptBundle hoặc StyleBundle, trong đó việc giảm thiểu xảy ra tự động.
- Để vô hiệu hóa tính năng này, có thể sử dụng đối tượng cơ bản Bundle.
Code Snippet 22:
public static void RegisterBundles(BundleCollection bdl) {
#if DEBUG
bdl.Add(new Bundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
bdl.Add(new Bundle("~/Content/CSS").Include(
"~/Content/site.css"));
#else
bdl.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
bdl.Add(new StyleBundle("~/Content/CSS").Include(
"~/Content/site.css"));
#endif
}
Giải thích:
- DEBUG mode: Sử dụng đối tượng cơ bản Bundle để dễ dàng gỡ lỗi (debugging).
- Release mode: Thực hiện bundling và giảm thiểu (minification) để cải thiện hiệu suất.
Việc này đảm bảo rằng các tệp không được gói (bundled) sẽ được sử dụng trong quá trình debug, nhưng trong chế độ phát hành (release), các tệp sẽ được gói và giảm thiểu để tối ưu hóa.
Các Khu vực (Areas) trong ASP.NET MVC
Mẫu dự án ASP.NET MVC cho phép phân tách mã nguồn ứng dụng dựa trên trách nhiệm của từng nhóm đảm nhiệm. Khi một ứng dụng MVC mới được tạo, các thư mục sau sẽ được tạo trong thư mục gốc:
- Controllers
- Models
- Views

Ở cấp cao nhất, dự án ASP.NET MVC bao gồm các thư mục:
- Controllers,
- Views,
- Models.
Mô tả các thư mục:
- Controllers: Chứa nhiều controller, mỗi controller đảm nhiệm một nhóm chức năng cụ thể.
- Views: Chứa các tệp .cshtml tương ứng với từng controller. Tên thư mục con trong Views sẽ khớp với tên của controller.
- Models: Chứa các tệp đại diện cho cấu trúc dữ liệu của ứng dụng.
Các Action trong controller sẽ được ánh xạ (mapped) tới các tệp View (.cshtml).
Phân loại theo Areas
Phân loại này hoạt động tốt khi số lượng controller và view còn ít. Tuy nhiên, khi số lượng tăng lên, việc tổ chức và quản lý mã nguồn trở nên cần thiết để đảm bảo hiệu quả. Areas được sử dụng để giải quyết vấn đề này.
- Areas: Là các nhóm logic bao gồm Controllers, Views, Models, và các tệp liên quan khác được nhóm vào một module trong ứng dụng.
Ví dụ:
- Một thư mục Area ở cấp cao nhất có thể bao gồm nhiều module.
- Phân vùng này giúp viết mã có tính bảo trì cao hơn bằng cách phân tách mã theo từng module cụ thể.
Mỗi Area bao gồm:
- Models: Định nghĩa dữ liệu và logic nghiệp vụ.
- Views: Xây dựng giao diện.
- Controllers: Điều phối logic.
- Routes: Định tuyến các yêu cầu HTTP.
Ví dụ minh họa: Cổng thông tin sinh viên
Một cổng thông tin sinh viên thường được chia thành các khu vực chức năng (Areas) như sau:
- Khu vực dành cho sinh viên (Student Area):
- Sinh viên có thể tạo hồ sơ, chỉnh sửa thông tin, và tải tài liệu lên.
- Khu vực dành cho giảng viên (Professor Area):
- Giảng viên có thể tạo và quản lý bài tập, xem hiệu suất học tập của sinh viên.
- Khu vực dành cho quản trị viên (Administrator Area):
- Quản trị viên có thể xử lý yêu cầu và quản lý toàn bộ ứng dụng.
Quy trình tạo Area trong ứng dụng MVC
- Trong Solution Explorer, nhấp chuột phải vào tên dự án.
- Chọn Add Area.
- Đặt tên cho khu vực (ví dụ: Student) và nhấp Add. Thư mục Areas với thư mục con cho Student sẽ được tạo. Tương tự, bạn có thể thêm nhiều Area khác.
- Lặp lại bước 1 đến 3 để tạo các Area cho Professor và Administrator.
- Các thư mục được tạo sẽ bao gồm các thư mục con tương ứng: Controllers, Views, và Models.
- Một tệp AreaRegistration.cs cũng được tạo. Tệp này chứa mã để đăng ký tuyến (route) cho từng Area.
- Vào Global.asax.cs và sửa đổi phương thức
Application_Start()
. Phương thức này chứa mã để đăng ký các Area trong ứng dụng.
Code Snippet 23: Đăng ký Area trong Application_Start()
protected void Application_Start() {
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
- Thêm HomeController vào các Area sau:
- Student
- Professor
- Administrator
- Main Area
Code Snippet 24 minh họa đoạn mã được tạo tự động sau khi thêm Area.
Phương thức Index() trong HomeController sẽ là một phần của tất cả các HomeControllers trong các Area này.
public class HomeController : Controller {
public ActionResult Index() {
return View();
}
}
7. Trong các Area, chèn các tệp View Index
vào các thư mục tương ứng với nội dung sau:
- Main Area:
<h1>Main Area Index View</h1>
- Student Area:
<h1>Student Area Index View</h1>
- Professor Area:
<h1>Professor Area Index View</h1>
- Admin Area:
<h1>Admin Area Index View</h1>
8. Tạo ứng dụng và điều hướng tới /MVCDemo
. Nếu có lỗi hiển thị, hãy chỉnh sửa bằng cách thêm phương thức RegisterAreas()
vào tệp RouteConfig.cs và gọi trong phương thức Application_Start
.
Code Snippet 25: Cấu hình định tuyến (Routing)
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "MVCDemo.Controllers" }
);
}
Giải thích:
- IgnoreRoute: Bỏ qua các tài nguyên như
.axd
. - MapRoute: Định nghĩa định tuyến mặc định, ánh xạ
HomeController
với hành độngIndex
. - Namespaces: Xác định không gian tên (namespace)
MVCDemo.Controllers
để tránh xung đột.
9. Nếu /MVCDemo/Student
hiển thị lỗi như “Resource cannot be found”, cần sửa bằng cách:
- Thêm
RegisterArea()
vào cấu hình. - Đảm bảo tệp
StudentAreaRegistration.cs
trong thư mụcStudent
đã được chỉnh sửa như hướng dẫn.
Code Snippet 26: Định nghĩa StudentAreaRegistration
public class StudentAreaRegistration : AreaRegistration {
public override string AreaName {
get { return "Student"; }
}
public override void RegisterArea(AreaRegistrationContext context) {
context.MapRoute(
"Student_default",
"Student/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
}
Mô tả:
- StudentAreaRegistration: Đăng ký khu vực (area) Student và ánh xạ các tuyến đường (routes) cụ thể cho khu vực này.
- MapRoute: Định nghĩa cấu trúc URL cho khu vực Student, ví dụ:
Student/{controller}/{action}/{id}
. - Action mặc định là
Index
và tham sốid
là tùy chọn.
Liên kết di chuyển giữa các Area
Sử dụng HTML helper ActionLink() để tạo các liên kết giúp người dùng di chuyển giữa các khu vực (areas) khác nhau. Sau khi tên khu vực được xác định, bạn có thể chuyển từ area này sang area khác bằng cách nhấp vào liên kết tương ứng.
Khắc phục lỗi với MVC Demo
- Khi mở /MVCDemo/Student, lỗi có thể xảy ra nếu System.Web.Optimization chưa được tham chiếu.
- Để khắc phục:
- Mở Package Manager Console trong Visual Studio.
- Nhập lệnh:
Install-Package Microsoft.AspNet.Web.Optimization
- Nhấn Enter để cài đặt.
Chia sẻ Dữ liệu (Data Sharing)
Bất kỳ dữ liệu nào được gửi từ một ứng dụng web tới máy chủ đều được xem là quan trọng. Dữ liệu có thể được gửi từ một trang của website tới một trang khác, nơi các tác vụ nghiệp vụ được thực hiện.
Ví dụ:
- Lưu trữ giá trị dữ liệu trên máy chủ, sau đó xóa hoặc chỉnh sửa dữ liệu đã lưu.
- Những tác vụ này thường khó khăn nếu không có sự hỗ trợ từ framework. Để thực hiện, ASP.NET cung cấp các phương pháp chia sẻ dữ liệu.
Phương pháp chia sẻ dữ liệu từ Controller tới View trong ASP.NET MVC:
ViewData: Một từ điển chứa dữ liệu, dễ dàng truyền từ controller tới view.
- ViewBag: Tương tự như ViewData, nhưng là một dynamic object.
- TempData: Lưu trữ dữ liệu tạm thời, sử dụng để chuyển dữ liệu giữa các request.
- Strongly Typed Views: View nhận dữ liệu từ model được định kiểu mạnh (strongly typed).
ViewData
ViewData được gọi là một đối tượng kiểu cặp khóa-giá trị (Key/Value Pair) hoặc một đối tượng Dictionary. Sử dụng ViewData, các nhà phát triển có thể truyền dữ liệu từ controller sang view.
- Kiểu dữ liệu của ViewData: Mặc định là một đối tượng của lớp ViewDataDictionary.
- Cách hoạt động: Chuỗi (string) được sử dụng làm khóa để lưu trữ và truy cập giá trị hoặc dữ liệu từ ViewData.

- Controller lưu trữ dữ liệu trong
ViewData["Name"] = "Roger Smith";
. - View truy cập giá trị này và hiển thị dữ liệu.
Ví dụ triển khai ViewData
Giả định:
- Một ứng dụng MVC có tên StudentManagement được tạo.
- Mô hình (Model) được gọi là Course.
- ViewData được sử dụng để truyền danh sách các khóa học từ controller sang view.
Code Snippet 27: Truyền dữ liệu qua ViewData
public ActionResult Index() {
List<Course> courseList = new List<Course>();
courseList.Add(new Course() {
CourseName = "Working with ASP.NET MVC"
});
courseList.Add(new Course() {
CourseName = "Working with Azure"
});
courseList.Add(new Course() {
CourseName = "Working with Python"
});
ViewData["Courses"] = courseList;
return View();
}
Giải thích:
- Một danh sách các khóa học (
courseList
) được tạo và thêm các khóa học vào. - Dữ liệu này được lưu trữ trong ViewData[“Courses”] để truyền sang view.
Code Snippet 28: Hiển thị dữ liệu trong Razor View
@model StudentManagement.Models.Course
@using StudentManagement.Models
<ul>
@foreach (var std in ViewData["Courses"] as List<Course>) {
<li>@std.CourseName</li>
}
</ul>
Giải thích:
- Sử dụng Razor syntax để hiển thị danh sách các khóa học.
- ViewData[“Courses”] được chuyển đổi thành danh sách (
List<Course>
) và duyệt qua bằng vòng lặpforeach
.
Sử dụng ViewData
Ví dụ: Code Snippet 29
public ActionResult Index() {
ViewData.Add("CourseId", 1);
ViewData.Add(new KeyValuePair<string, object>("CourseName", "Working with Python"));
ViewData.Add(new KeyValuePair<string, object>("Duration", 20));
return View();
}
Giải thích:
- Dữ liệu được thêm vào ViewData dưới dạng cặp khóa-giá trị (KeyValuePair).
- Trong View, cần ép kiểu và chỉ định kiểu dữ liệu chính xác để sử dụng các giá trị này.
ViewBag
ViewBag là một cách khác để truyền dữ liệu từ controller tới view:
- Dynamic Object: ViewBag là thuộc tính động của lớp cơ sở của tất cả các controller, tức là ControllerBase.
- Dữ liệu tạm thời: Dữ liệu được lưu trữ trong ViewBag là tạm thời, chỉ tồn tại trong một request.
Hình 6.3: Truyền dữ liệu qua ViewBag
- Controller:
ViewBag.Name = "Roger Smith";
- View: Truy cập giá trị này qua
@ViewBag.Name
.
Các đặc điểm của ViewBag
- Dễ sử dụng:
- Truy cập dữ liệu trong View thông qua cú pháp Razor, ví dụ:
@ViewBag.Name
.
- Truy cập dữ liệu trong View thông qua cú pháp Razor, ví dụ:
- Linh hoạt:
- Nhiều thuộc tính và giá trị có thể được gán vào ViewBag. Tuy nhiên:
- Nếu cùng một thuộc tính được gán nhiều giá trị, chỉ giá trị cuối cùng sẽ được lưu.
- Nhiều thuộc tính và giá trị có thể được gán vào ViewBag. Tuy nhiên:
- Hạn chế:
- ViewBag không duy trì trạng thái (stateless).
- Dữ liệu chỉ có thể truyền từ controller sang view.
- Không thể truyền dữ liệu giữa các view hoặc giữa các controller.
Ví dụ: Thiết lập ViewBag
Giả định:
- Ứng dụng MVC được tạo với model có tên Employee.
Code Snippet 30 sẽ minh họa cách sử dụng ViewBag trong phương thức hành động (action method).
IList<Employee> employeeList;
public HomeController() {
employeeList = new List<Employee>() {
new Employee() { EmployeeID = 1, EmployeeName = "Steve Jones", Age = 21 },
new Employee() { EmployeeID = 2, EmployeeName = "Bill Kin", Age = 25 },
new Employee() { EmployeeID = 3, EmployeeName = "Carrie Swan", Age = 20 },
new Employee() { EmployeeID = 4, EmployeeName = "Ron Dixon", Age = 31 },
new Employee() { EmployeeID = 5, EmployeeName = "Rob Tucker", Age = 19 }
};
}
public ActionResult Index() {
ViewBag.TotalEmployees = employeeList.Count;
return View();
}
Giải thích:
- employeeList chứa danh sách các nhân viên.
- Tổng số nhân viên (
employeeList.Count
) được gán cho thuộc tính ViewBag.TotalEmployees. - Dữ liệu này sau đó được hiển thị trong View.
Code Snippet 31: Hiển thị dữ liệu trong View
<label>Total Employees:</label> @ViewBag.TotalEmployees
Kết quả:
- Tổng số nhân viên hiển thị là 5.
- Không cần ép kiểu khi truy xuất giá trị từ ViewBag.
Lưu ý về ViewData và ViewBag
- Điểm chung:
- Cả hai đều sử dụng đối tượng Dictionary nội bộ.
- Không thể sử dụng cùng một tên (key) trong cả ViewData và ViewBag, nếu không sẽ gây lỗi runtime.
Code Snippet 32: Lỗi khi trùng key giữa ViewData và ViewBag
ViewBag.CourseId = 1;
ViewData.Add("CourseId", 1); // Lỗi runtime vì đã tồn tại key "CourseId"
TempData
- TempData được sử dụng để chia sẻ dữ liệu giữa các yêu cầu (requests) hiện tại và tiếp theo.
- Đặc điểm:
- Thời gian tồn tại ngắn (short-lived).
- Dữ liệu sẽ bị xóa sau khi được đọc hoặc khi hết phiên (session).
Cách hoạt động:
- Giữ dữ liệu qua Redirect:
- Khi chuyển hướng (redirect) tới một view khác, TempData giúp truyền dữ liệu giữa các yêu cầu.
- Tự động xóa:
- Dữ liệu TempData sẽ bị xóa sau khi sử dụng.
Ưu điểm:
- Hữu ích khi cần chia sẻ dữ liệu tạm thời giữa các controller hoặc view.
Code Snippet 33: Gán giá trị cho TempData
public class WebController : Controller {
public ActionResult Index() {
TempData["Message"] = "Welcome to ASP.NET MVC!";
return View();
}
}
Giải thích:
- TempData[“Message”] chứa giá trị
"Welcome to ASP.NET MVC!"
. - Dữ liệu này sẽ tồn tại khi chuyển sang view
Hiển thị dữ liệu TempData trong View
Để hiển thị dữ liệu TempData trong View, thực hiện các bước sau:
- Nhấp chuột phải vào phương thức Index trong lớp controller.
- Chọn Add View.
- Đặt tên View phù hợp, chẳng hạn Index.cshtml. Mở tệp View và viết đoạn mã sau để hiển thị dữ liệu:
Code Snippet 34:
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
@TempData["Message"]
- Thực thi đoạn mã để kiểm tra kết quả.
Lưu ý:
- Sử dụng TempData.Keep(“key”) để giữ giá trị TempData cho request tiếp theo sau khi đọc.
- Sử dụng TempData.Remove(“key”) để xóa giá trị TempData ngay từ request hiện tại.
Strongly Typed View
Strongly Typed View là một View liên kết trực tiếp với một model cụ thể.
- Đặc điểm:
- Bất kỳ class nào cũng có thể được liên kết với View.
- Các thuộc tính của model có thể được truy cập trực tiếp trong View.
- Hỗ trợ cả các kiểu dữ liệu tùy chỉnh và nguyên thủy như string, int, array.
Code Snippet 35: Truyền một đối tượng đến Strongly Typed View
public ActionResult StudentCourse() {
StudentCourseModel courseModel = new StudentCourseModel();
return View(courseModel);
}
Code Snippet 36: Hiển thị dữ liệu trong Strongly Typed View
@Html.DisplayFor(modelItem => item.CourseId)
Giải thích:
- Đối tượng
StudentCourseModel
được truyền từ controller đến View. - Giá trị của
CourseId
được liên kết trực tiếp và hiển thị trong View.
Chức năng của Strongly Typed View
Sử dụng lại đối tượng:
- Khi gửi dữ liệu (post), có thể sử dụng lại cùng một đối tượng.
Code Snippet 37: Xử lý Post Action
[HttpPost]
public ActionResult View(UseModel obj) {
obj.Save();
return View();
}
Giải thích:
- Dữ liệu của đối tượng
obj
có thể được lưu (save) trên server và xử lý thêm.
Lợi ích chính của Strongly Typed View:
- Tự động ánh xạ: Tự động ánh xạ các thuộc tính model đến View.
- Hỗ trợ IntelliSense: Giúp lập trình viên viết mã dễ dàng hơn trong Visual Studio.
- Kiểm tra kiểu dữ liệu tại thời gian biên dịch: Giảm thiểu lỗi runtime do không khớp kiểu.
Kỹ thuật chia sẻ dữ liệu (Data Sharing Techniques)
Trong khi các yêu cầu (requests) được xử lý và dữ liệu được chuẩn bị bởi các phương thức hành động (action methods) trong controller, View đóng vai trò hiển thị kết quả này tới người dùng.
Các phương pháp chia sẻ dữ liệu từ Controller tới View
Các phương pháp dưới đây được sử dụng để truyền dữ liệu từ controller đến view trong ASP.NET MVC:
- ViewData
- ViewBag
- TempData
- Strongly Typed View
ViewData, ViewBag, và TempData là các đối tượng trong ASP.NET MVC, hỗ trợ truyền dữ liệu trong các tình huống sau:
- Từ Controller đến View.
- Từ một Controller đến một Controller khác.
- Từ một Action đến một Action khác.
- Giữa các HTTP Request liên tiếp.
So sánh các kỹ thuật chia sẻ dữ liệu
- ViewBag:
- Là một đối tượng dynamic giúp truyền dữ liệu từ controller sang view.
- Không yêu cầu khai báo kiểu dữ liệu trước.
- ViewData:
- Là một đối tượng Dictionary (cặp khóa-giá trị) dùng để truyền dữ liệu từ controller sang view.
- Cần ép kiểu dữ liệu khi truy xuất.
- TempData:
- Là một đối tượng Dictionary dùng để truyền dữ liệu giữa các request HTTP liên tiếp.
- Thường được sử dụng khi cần chia sẻ dữ liệu qua các lần redirect.
Khi nào sử dụng ViewData và ViewBag?
- Sử dụng khi:
- Hiển thị dữ liệu động như danh sách thả xuống.
- Truyền dữ liệu nhỏ gọn giữa controller và view.
- Truyền thông tin tạm thời như tin nhắn lỗi hoặc thông báo.
So sánh ViewData, ViewBag, và TempData
Thuộc tính | ViewData | ViewBag | TempData |
---|---|---|---|
Loại dữ liệu | Dictionary | Dynamic Object | Dictionary |
Phạm vi sử dụng | Từ Controller đến View | Từ Controller đến View | Giữa các request HTTP |
Ép kiểu dữ liệu | Cần ép kiểu khi truy cập dữ liệu | Không cần ép kiểu | Cần ép kiểu khi truy cập dữ liệu |
Thời gian sống | Trong một request | Trong một request | Giữ dữ liệu đến khi được đọc xong hoặc hết phiên làm việc |
Tình huống sử dụng | Truyền dữ liệu nhỏ giữa Controller và View | Truyền dữ liệu nhỏ giữa Controller và View | Truyền dữ liệu qua các lần Redirect hoặc giữa các Controller |
Tóm lại:
- ViewData và ViewBag phù hợp để truyền dữ liệu nhỏ gọn trong một request.
- TempData thích hợp để truyền dữ liệu giữa các request hoặc sau khi Redirect.
Bài tập
1. Tạo ứng dụng ASP.NET MVC cơ bản
- Tạo một ứng dụng ASP.NET MVC với một controller và view để hiển thị một thông báo đơn giản.
2. Mở rộng ứng dụng với xử lý đầu vào
- Mở rộng ứng dụng trước đó để:
- Bao gồm một biểu mẫu nhập dữ liệu từ người dùng.
- Xử lý gửi biểu mẫu.
- Tối ưu hiệu suất ứng dụng bằng cách triển khai bundling và minification cho các tệp CSS và JavaScript.
3. Tạo mô hình dữ liệu và CRUD cho quản lý sách
- Tạo một lớp model có tên Book với các thuộc tính:
- Id, Title, Author, Genre, Price.
- Triển khai CRUD (Create, Read, Update, Delete) để quản lý sách.
- Sử dụng Entity Framework Code First để truy cập dữ liệu và quản lý cơ sở dữ liệu.
Tạo các View và phương thức Action trong BooksController
:
a. Hiển thị danh sách tất cả sách.
b. Xem chi tiết của một quyển sách cụ thể.
c. Thêm một quyển sách mới.
d. Chỉnh sửa một quyển sách hiện có.
e. Xóa một quyển sách.
4. Tạo ứng dụng ASP.NET MVC để quản lý blog
-
Thiết kế một ứng dụng blog đơn giản, cho phép người dùng:
- Tạo, xem, cập nhật và xóa bài đăng blog.
-
Thiết kế lược đồ cơ sở dữ liệu gồm hai bảng:
- Posts: chứa cột Id, Title, Content, Author, DateCreated.
- Comments: chứa cột Id, PostId (khóa ngoại đến bảng
Posts
), Author, Content, DateCreated.
-
Triển khai CRUD để quản lý bài đăng và bình luận.
-
Sử dụng Entity Framework Code First để quản lý cơ sở dữ liệu.
Tạo các View và phương thức Action trong PostsController
:
a. Hiển thị danh sách tất cả bài đăng.
b. Xem chi tiết một bài đăng cùng với bình luận.
c. Thêm một bài đăng mới.
d. Chỉnh sửa một bài đăng hiện có.
e. Xóa một bài đăng.
f. Thêm một bình luận mới vào bài đăng.