ViewData is a container for data to be passed from the PageModel to the content page. ViewData is a dictionary of objects with a string-based key. You add items to ViewData as follows:
public class IndexModel : PageModel
{
public void OnGet()
{
ViewData["MyNumber"] = 42;
ViewData["MyString"] = "Hello World";
ViewData["MyComplexObject"] = new Book {
Title = "Sum Of All Fears",
Author = new Author { Name = "Tom Clancy" },
Price = 5.99m
};
}
}
The ViewData dictionary is automatically made available to the content page. Therefore, in order to reference values stored in it, you just refer to their item by key:
@page
@model IndexModel
@{
}
<h2>@ViewData["MyString"]</h2>
<p>The answer to everything is @ViewData["MyNumber"]</p>
When working with non-string values, you need to cast them to their correct type in the content page:
@page
@model IndexModel
@{
var book = (Book)ViewData["MyComplexObject"];
}
<h2>@book.Title</h2>
<p>@book.Author.Name</p>
<p>@book.Price</p>
You don't need to cast if you only want to render the value, and the ToString()
method renders the value that you want.
ViewData Attribute
The ViewData
attribute was introduced in ASP.NET Core 2.1. PageModel properties decorated with this attribute are automatically added as keys to the ViewData dictionary along with any value that has been assigned to them. In the following example, the Message
property has been automatically added to ViewData:
public class IndexModel : PageModel
{
[ViewData]
public string Message { get; set; }
public void OnGet()
{
Message = "Hello World";
}
}
Now the Message
property can be accessed in the view via the Model
property or the ViewData dictionary:
@page
@model IndexModel
@{
}
<h2>@Model.Message</h2>
<h2>@ViewData["Message"]</h>
You should prefer to access properties of the Model
in a content page because you benefit from strong typing: IntelliSense and compile-time checking. So why should you use the ViewData attribute on model properties? The real benefit of this feature comes when working with layout pages. ViewData is shared with the layout page (and any partial pages called by the content page or the layout), so the attribute makes it easy to pass typed data from the PageModel to the layout page or partials without having to explicitly assign it to the ViewData dictionary.
Building on the previous example, the following snippet is a partial named _HelloWorldPartial:
<p>@ViewData["Message"] from the Hello World partial</p>
This is called from within the layout page using the partial tag helper:
<partial name="_HelloWorldPartial" />
The PageModel Message
property was set in the OnGet
handler and assigned to ViewData via the attribute, which ensures that it is passed from content page to layout to partial where it is rendered:
ViewBag In Razor Pages
ViewBag
is a wrapper around the ViewData dictionary and provides an alternative way to access ViewData contents within ASP.NET Core MVC controllers using dynamic properties instead of string-based indexes. A design decision was made NOT to include a ViewBag
property in the Razor Pages PageModel class, but you can use ViewBag
to reference ViewData entries from within a Razor content page or layout page:
@page
@model IndexModel
@{
ViewBag.Title = "My Home Page";
}
You can access this within the layout page either via ViewBag
or ViewData:
<title>@ViewBag.Title</title>
<title>@ViewData["Title"]</title>
Either approach will render "My Home Page" within the title
element. As to which approach you use, the ViewBag
syntax is slightly more terse and does not require you to cast non-string values, but you should bear in mind the reason that ViewBag
was not included in the PageModel class in the first place:
Damian Edwards from the ASP.NET Core team
ViewBag
usesdynamic
which in our testing introduces a measurable performance impact on the processing of pages or views that use it.