ViewBag dùng dynamic feature giới thiệu trong C# 4.0. Nó cho phép object có properties được thêm động. Nội bộ, nó là dynamic type property của ControllerBase class (base class của Controller).
ViewBag chỉ transfer data từ controller sang view, không ngược lại. ViewBag values sẽ null nếu redirection xảy ra. ViewBag có thể set và get value động và thêm bất kỳ số lượng additional fields nào mà không cần convert strongly typed.
Lưu data vào ViewBag
ViewBag.Counties = countriesList;
Lấy data từ ViewBag
string country = ViewBag.Countries;
Controller
Ví dụ
using System.Collections.Generic;
using System.Web.Mvc;
namespace DemoMvcApplication.Controllers {
public class HomeController : Controller {
public ViewResult Index() {
ViewBag.Countries = new List<string> {
"India", "Malaysia", "Dubai", "USA", "UK"
};
return View();
}
}
}
View
@{
ViewBag.Title = "Countries List";
}
<h2>Countries List</h2>
<ul>
@foreach(string country in ViewBag.Countries) {
<li>@country</li>
}
</ul>
Output
Hiển thị danh sách countries.
ViewBag vs ViewData vs TempData vs Model
| Đặc điểm | ViewData | ViewBag | TempData | ViewModel (Model) |
|---|---|---|---|---|
| Kiểu dữ liệu | Dictionary<string, object> | DynamicObject (wrapper ViewData) | Dictionary (session-backed) | Strongly typed class |
| Syntax | ViewData["Key"] | ViewBag.Key | TempData["Key"] | @model Type |
| Type Safety | Không (cast runtime) | Không (dynamic) | Không | ✅ Compile-time |
| IntelliSense | Không | Có (limited) | Không | ✅ Full |
| Lifetime | Current request | Current request | Next request (survive redirect) | Current request |
| Performance | Nhanh | Chậm hơn (DLR overhead) | Chậm (session) | Nhanh |
Khi nào dùng ViewBag
- Dữ liệu đơn giản, ít property (Title, Message, Flag)
- Prototype nhanh, demo
- View-specific data không cần validation
Khi KHÔNG nên dùng ViewBag
- Dữ liệu phức tạp, nhiều properties
- Cần validation, type safety
- Team lớn, cần maintainability
- Data pass qua nhiều layers
Best Practice: Strongly Typed ViewModel
// ViewModel
public class HomeIndexViewModel {
public string Title { get; set; }
public List Countries { get; set; }
public int TotalCountries => Countries?.Count ?? 0;
public DateTime GeneratedAt { get; set; } = DateTime.Now;
}
// Controller
public ViewResult Index() {
var model = new HomeIndexViewModel {
Title = "Countries List",
Countries = new List { "India", "Malaysia", "Dubai", "USA", "UK" }
};
return View(model);
}
// View
@model HomeIndexViewModel
@Model.Title
Total: @Model.TotalCountries countries
@foreach (var country in Model.Countries) {
- @country
}
ViewBag Dynamic Internals
// ViewBag thực chất là:
public dynamic ViewBag => new DynamicViewData(ViewData);
// DynamicViewData implementation (simplified)
public class DynamicViewData : DynamicObject {
private readonly ViewDataDictionary _viewData;
public override bool TryGetMember(GetMemberBinder binder, out object result) {
_viewData.TryGetValue(binder.Name, out result);
return true; // Luôn true - không throw nếu key không tồn tại
}
public override bool TrySetMember(SetMemberBinder binder, object value) {
_viewData[binder.Name] = value;
return true;
}
}