ViewBag, ViewData và TempData trong ASP.NET MVC

ViewBag trong ASP.NET MVC

ViewBag là gì?

ViewBag trong ASP.NET MVC được sử dụng để chuyển dữ liệu tạm thời (không có trong model) từ controller sang view.

ViewBag là một thuộc tính kiểu dynamic của lớp  ControllerBase là lớp cơ sở của lớp Controller.

Hình sau minh họa ViewBag.

ViewBag trong ASP.NET MVC

Trong hình trên, thuộc tính Name được gắn vào ViewBag với ký hiệu dấu chấm và gán giá trị chuỗi "Bill" cho nó trong controller. Thuộc tính này có thể được truy cập trong view như sau @ViewBag.Name.

Bạn có thể gán bất kỳ số thuộc tính và giá trị nào cho ViewBag. Nếu bạn gán cùng một tên thuộc tính nhiều lần cho ViewBag, thì nó sẽ chỉ xem xét giá trị cuối cùng được gán cho thuộc tính.

Tips: Bạn có thể gán một đối tượng kiểu nguyên thủy hoặc kiểu phức tạp làm giá trị cho thuộc tính ViewBag.
Ghi chú: ViewBag chỉ truyền dữ liệu từ controller sang view, không chuyển dữ liệu ngược lại. Giá trị ViewBag sẽ là null nếu xảy ra chuyển hướng (redirect).

Ví dụ sau minh họa cách chuyển dữ liệu từ controller sang view bằng ViewBag.

namespace MVC_BasicTutorials.Controllers
{
    public class StudentController : Controller
    {
        IList<Student> studentList = new List<Student>() 
        { 
            new Student() { StudentID=1, StudentName="Steve", Age = 21 },
            new Student() { StudentID=2, StudentName="Bill", Age = 25 },
            new Student() { StudentID=3, StudentName="Ram", Age = 20 },
            new Student() { StudentID=4, StudentName="Ron", Age = 31 },
            new Student() { StudentID=5, StudentName="Rob", Age = 19 }
        };
        
        // GET: Student
        public ActionResult Index()
        {
            ViewBag.TotalStudents = studentList.Count();

            return View();
        }

    }
}

Trong ví dụ trên, chúng tôi muốn hiển thị tổng số sinh viên trong view. Vì vậy, chúng tôi đã gắn giá trị của studentList.Count() cho thuộc tính TotalStudents  của ViewBag.

Bây giờ, trong view Index.cshtml, bạn có thể truy cập thuộc tính ViewBag.TotalStudents, như được hiển thị bên dưới.

<label>Total Students:</label> @ViewBag.TotalStudents

Đầu ra:

Total Students: 5

Trong thực tế, ViewBag là một trình bao bọc xung quanh ViewData. Nó sẽ ném ra một ngoại lệ thời gian chạy nếu tên thuộc tính ViewBag khớp với khóa của ViewData.

Hạn chế của ViewBag

  • ViewBag không yêu cầu ép kiểu trong khi truy xuất các giá trị từ nó. Điều này có thể ném ra một ngoại lệ thời gian chạy nếu sử dụng sai phương thức trên giá trị.
  • ViewBag là kiểu dynamic và bỏ qua kiểm tra kiểu tại thời điểm biên dịch. Vì vậy, tên thuộc tính ViewBag phải khớp trong controller và view khi viết nó theo cách thủ công.

ViewData trong ASP.NET MVC

Trong ASP.NET MVC, ViewData tương tự như ViewBag, truyền dữ liệu từ Controller sang View. ViewData có kiểu Dictionary, trong khi ViewBag là kiểu dynamic. Tuy nhiên, cả hai đều lưu trữ dữ liệu trong cùng một từ điển nội bộ.

ViewData là một từ điển, vì vậy nó chứa các cặp khóa-giá trị trong đó mỗi khóa phải là một chuỗi.

Hình sau minh họa ViewData.

ViewData trong ASP.NET MVC
Ghi chú: ViewData chỉ chuyển dữ liệu từ controller sang view nhưng không phải ngược lại. Nó chỉ tồn tại trong yêu cầu hiện tại.

Ví dụ sau minh họa cách chuyển dữ liệu từ controller sang view bằng ViewData.

public ActionResult Index()
{
    IList<Student> studentList = new List<Student>();
    studentList.Add(new Student() { StudentName = "Bill" });
    studentList.Add(new Student() { StudentName = "Steve" });
    studentList.Add(new Student() { StudentName = "Ram" });

    ViewData["students"] = studentList;
  
    return View();
}

Trong ví dụ trên, studentList được gán cho ViewData["students"] với "students" là khóa và studentList là giá trị. Bây giờ bạn có thể truy cập ViewData["students"] trong view, như hình dưới đây.

<ul>
@foreach (var std in ViewData["students"] as IList<Student>)
{
    <li>
        @std.StudentName
    </li>
}
</ul>

Ở trên, chúng ta truy xuất giá trị bằng cách sử dụng ViewData["students"] và ép kiểu nó về một kiểu dữ liệu thích hợp. Bạn cũng có thể thêm các đối tượng KeyValuePair vào ViewData, như được hiển thị bên dưới.

public ActionResult Index()
{
    ViewData.Add("Id", 1);
    ViewData.Add(new KeyValuePair<string, object>("Name", "Bill"));
    ViewData.Add(new KeyValuePair<string, object>("Age", 20));

    return View();
}

ViewData và ViewBag đều sử dụng cùng một từ điển trong nội bộ. Vì vậy, bạn không thể để ViewData Key trùng với tên thuộc tính của ViewBag, nếu không nó sẽ ném ra một ngoại lệ lúc thực thi.

public ActionResult Index()
{
    ViewBag.Id = 1;

    ViewData.Add("Id", 1); // throw runtime exception as it already has "Id" key
    ViewData.Add(new KeyValuePair<string, object>("Name", "Bill"));
    ViewData.Add(new KeyValuePair<string, object>("Age", 20));

    return View();
}

TempData trong ASP.NET MVC

TempData được sử dụng để chuyển dữ liệu từ view sang controller, controller sang view hoặc từ phương thức hành động này sang phương thức hành động khác của cùng một controller hoặc một controller khác.

TempData lưu trữ dữ liệu tạm thời và tự động xóa dữ liệu đó sau khi truy xuất giá trị.

TempData là một thuộc tính trong lớp ControllerBase. Vì vậy, nó có sẵn trong bất kỳ controller hoặc view nào trong ứng dụng ASP.NET MVC.

Ví dụ sau đây cho thấy cách chuyển dữ liệu từ phương thức hành động này sang phương thức hành động khác bằng TempData.

public class HomeController : Controller
{
    public ActionResult Index()
    {
        TempData["name"] = "Bill";

        return View();
    }

    public ActionResult About()
    {
        string name;
        
        if(TempData.ContainsKey("name"))
        {
            name = TempData["name"].ToString(); // returns "Bill" 
        }

        return View();
    }

    public ActionResult Contact()
    {
        //the following throws exception as TempData["name"] is null 
        //because we already accessed it in the About() action method
        //name = TempData["name"].ToString(); 

        return View();
    }
}

Trong ví dụ trên, chúng tôi đã thêm dữ liệu vào TempData trong phương thức hành động Index() và truy cập nó trong phương thức hành động About(). Giả sử rằng người dùng sẽ truy cập trang đầu tiên Index và sau đó đến trang About.

Phần sau chuyển dữ liệu từ phương thức hành động sang view.

public class HomeController : Controller
{
    public ActionResult Index()
    {
        TempData["name"] = "Bill";

        return View();
    }

    public ActionResult About()
    {
        //the following throws exception as TempData["name"] is null 
        //because we already accessed it in the Index.cshtml view
        //name = TempData["name"].ToString(); 

        return View();
    }

    public ActionResult Contact()
    {
        //the following throws exception as TempData["name"] is null 
        //because we already accessed it in the Index.cshtml view
        //name = TempData["name"].ToString(); 

        return View();
    }
}

Ở trên, chúng ta đã thêm dữ liệu vào TempData trong phương thức hành động Index(). Vì vậy, chúng ta có thể truy cập nó trong view Index.cshtml, như hình dưới đây. Bởi vì chúng ta đã truy cập nó trong view Index trước, chúng ta không thể truy cập nó ở bất kỳ nơi nào khác.

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@TempData["name"]

Bạn cũng có thể chuyển dữ liệu từ view sang controller, như được hiển thị bên dưới.

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@{
    TempData["name"] = "Steve";
}

TempData ở trên có thể được truy cập trong controller, như hình dưới đây.

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult About()
    {
        if(TempData.ContainsKey("name"))
        {
            name = TempData["name"].ToString(); // returns "Bill" 
        }

        return View();
    }

    public ActionResult Contact()
    {
        //the following throws exception as TempData["name"] is null 
        //because we already accessed it in the About() action method
        //name = TempData["name"].ToString(); 

        return View();
    }
}

Mặc dù, TempData tự động xóa khóa-giá trị sau khi được truy cập, bạn vẫn có thể giữ nó cho yêu cầu tiếp theo bằng cách gọi phương thức TempData.Keep().

Ví dụ sau đây cho thấy cách giữ lại giá trị TempData cho các yêu cầu tiếp theo ngay cả khi đã truy cập nó.

public class HomeController : Controller
{
    public ActionResult Index()
    {
        TempData["name"] = "Bill";
        return View();
    }

    public ActionResult About()
    {
        string name;
        
        if(TempData.ContainsKey("name"))
        {
            name = TempData["name"] as string;            
        }
        
        TempData.Keep("name"); // Marks the specified key in the TempData for retention.
        
        //TempData.Keep(); // Marks all keys in the TempData for retention

        return View();
    }

    public ActionResult Contact()
    {
        string name;
        
        if(TempData.ContainsKey("name"))
        {
            data = TempData["name"] as string;
        }
            
        return View();
    }
}

Những điểm cần nhớ về ViewBag, ViewData và TempData trong ASP.NET MVC

  1. ViewBag chèn nội bộ dữ liệu vào từ điển ViewData. Vì vậy, khóa của ViewData và thuộc tính của ViewBag KHÔNG được trùng khớp.
  2. ViewBag chuyển dữ liệu từ Controller sang View, không phải ngược lại.
  3. ViewBag là một thuộc tính kiểu dynamic của lớp  ControllerBase là lớp cơ sở của lớp Controller
  4. ViewData chuyển dữ liệu từ Controller sang View, không phải ngược lại.
  5. ViewData là một loại từ điển.
  6. Tuổi thọ của ViewData chỉ kéo dài trong thời gian yêu cầu HTTP hiện tại. Giá trị ViewData sẽ bị xóa nếu xảy ra chuyển hướng.
  7. Giá trị ViewData phải được ép kiểu thành một kiểu thích hợp trước khi sử dụng nó.
  8. TempData được sử dụng để chuyển dữ liệu từ view sang controller, controller sang view hoặc từ phương thức hành động này sang phương thức hành động khác của cùng một controller hoặc một controller khác.
  9. TempData lưu trữ dữ liệu tạm thời và tự động xóa dữ liệu đó sau khi truy xuất giá trị.
  10. TempData là một loại từ điển.
  11. TempData tự động xóa khóa-giá trị sau khi được truy cập, bạn có thể giữ nó cho yêu cầu tiếp theo bằng cách gọi phương thức TempData.Keep().
ASP.NET MVC
Bài Viết Liên Quan:
Bundle và minify js, css trong ASP.NET MVC
Trung Nguyen 11/04/2021
Bundle và minify js, css trong ASP.NET MVC

Các kỹ thuật bundle (gộp file) và minify (rút gọn file) đã được giới thiệu trong ASP.NET MVC 4 để cải thiện thời gian tải trang.

Filter trong ASP.NET MVC
Trung Nguyen 10/04/2021
Filter trong ASP.NET MVC

Trong hướng dẫn này, bạn sẽ tìm hiểu filter trong ASP.NET MVC là gì? Có những loại filter nào và cách sử dụng filter trong ASP.NET MVC.

Layout View trong ASP.NET MVC
Trung Nguyen 10/04/2021
Layout View trong ASP.NET MVC

Trong hướng dẫn này, bạn sẽ tìm hiểu về Layout View là gì các cách sử dụng Layout View trong ASP.NET MVC.

Validation trong ASP.NET MVC
Trung Nguyen 10/04/2021
Validation trong ASP.NET MVC

Ở bài viết này, bạn sẽ học cách triển khai xác thực dữ liệu và hiển thị thông báo lỗi xác thực dữ liệu trong ứng dụng ASP.NET MVC.