Working With ViewData in Razor Pages

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 complex 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>

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:

ViewData in Razor Pages

ViewBag In Razor Pages

ViewBag is an alternative way to access the ViewData dictionary within ASP.NET Core MVC controllers. A design decision was made NOT to include a ViewBag property in the Razor Pages PageModel class, but you can use ViewBag to pass values from a Razor content page to a 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, 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 uses dynamic which in our testing introduces a measurable performance impact on the processing of pages or views that use it.

© 2019 - Learn Razor Pages.
All rights reserved.