liveBook · Manning

ViewBag

As explained in Pro ASP.NET Core 7, Tenth Edition

ViewBag is a dynamic ASP.NET Core MVC property bag for passing unstructured data from a controller or view component to a view.

ViewBag passes small amounts of unstructured data to an ASP.NET Core MVC view alongside its view model. A controller action inherits the ViewBag property from Controller; its dynamic object gains properties when you assign values to them. The view reads those values through its own ViewBag property. section 22.2

Add a price comparison to a product view

In HomeController.Index, assign `ViewBag.AveragePrice = await context.Products.AverageAsync(p => p.Price);`, then return the requested Product as the view model. In Views/Home/Index.cshtml, keep `@model Product?` and use `ViewBag.AveragePrice` in an expression that displays the product price as a percentage of the average. The extra value does not require a new view model class. section 22.2

Use ViewBag for a little supplementary data, not as a substitute for a considered view model. Dynamic properties are not checked by the compiler. If multiple actions use the same property, or one action adds more than two or three properties, create a view model class instead. section 22.2

Highlight the selected navigation category

A navigation view component can set `ViewBag.SelectedCategory = RouteData?.Values["category"]` while passing its category list as the view model. Its Razor view compares each category with `ViewBag.SelectedCategory` to choose a CSS class for the selected link. A unit test can supply route data through ViewComponentContext and read the selected value from the resulting ViewViewComponentResult. section 8.1.3

A view can also set a ViewBag property for its layout. For example, set `ViewBag.Title = "Product Table"` in the view and read it in `_Layout.cshtml`. A value assigned in the view takes precedence over one assigned by the action. To preserve the action's value, use `ViewBag.Title = ViewBag.Title ?? "Product Table"`; in the layout, provide a fallback when a view might not define Title. section 22.4.1

Listing 22.5 Using the view bag in the HomeController.cs file in the Controllers folder
using Microsoft.AspNetCore.Mvc;
using WebApp.Models;
using Microsoft.EntityFrameworkCore;

namespace WebApp.Controllers {

    public class HomeController : Controller {
        private DataContext context;
                
        public HomeController(DataContext ctx) {
            context = ctx;
        }
                
        public async Task<IActionResult> Index(long id = 1) {
            ViewBag.AveragePrice = 
                await context.Products.AverageAsync(p => p.Price);
            return View(await context.Products.FindAsync(id));
        }
                
        public IActionResult List() {
            return View(context.Products);
        }
    }
}

The controller listing shows an action assigning AveragePrice before returning a Product view model. section 22.2

Listing 22.6 Using the view bag in the Index.cshtml file in the Views/Home folder
@model Product?
<!DOCTYPE html>
<html>
<head>
    <link href="/lib/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
    <h6 class="bg-primary text-white text-center m-2 p-2">
        Product Table
    </h6>
    <div class="m-2">
        <table class="table table-sm table-striped table-bordered">
            <tbody>
                <tr><th>Name</th><td>@Model?.Name</td></tr>
                <tr>
                    <th>Price</th>
                    <td>
                        @Model?.Price.ToString("c")
                        (@(((Model?.Price / ViewBag.AveragePrice)
                               * 100).ToString("F2"))% of average price)     
                    </td>
                </tr>
                <tr><th>Category ID</th><td>@Model?.CategoryId</td></tr>
            </tbody>
        </table>
    </div>
</body>
</html>

The matching Razor listing shows the view model and ViewBag value used in the same price display. section 22.2

How Pro ASP.NET Core 7, Tenth Edition covers it

How deep it goes
Shows property assignment and consumption, a view-component test, and layout precedence; does not explain dynamic-object internals.
Examples
Uses an average-price display, selected-category navigation links, and a layout title.
What it assumes
Assumes familiarity with controller actions and Razor view models; explains dynamic ViewBag property assignment directly.
What you can do after
Apply it via ASP.NET Core MVC to pass supplementary values to views and configure layouts while recognizing when to use a view model.
How it connects
Connects ViewBag to view models, Razor views, view components, route data, and layouts.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Pro ASP.NET Core 7, Tenth Edition. The section links point to the parts of the book it draws on.