Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ViewBag not passing from base controller

We have converted our app to be ASP.NET Core but I am having a problem with the ViewBag populating correctly. We have the following base controller

public abstract class ControllerBase : Controller
{
    public ControllerBase()
    {
        ViewBag.Title = "MySite";
    }
  ...// lots of other stuff here also
}

All of our other controllers inherit from ControllerBase but by the time we get to the view and use the following

@{
    ViewBag.Title = ViewBag.Title + " - " + Model.PageTitle;
}

But in the view the ViewBag.Title is null. It does not cause an error but we end up with just " - MyPage" rather than "MySite - MyPage" for the browser title.

This all worked correctly in the previous version of .net, just not working now in ASP.NET Core. As I step through the debugger I see that the ControllerBase constructor is being called but the ViewBag data is not persisting.

This leaves me with two questions:

  1. Is there something new/different in ASP.NET Core which changed the scope of the ViewBag?
  2. What is the best way to fix this? (Without adding the value in a bunch of places.)

Edit: I set a debugger stop on the first line of the base controller and stepped through with the ViewBag.Title set as my watch variable. As I step through I can see the value get set and then I move from the base controller to the constructor for the specific action controller. As I step through that constructor the ViewBag.Title is still set. As soon as I hit the first line of the Index() method the ViewBag.Title turns to null.

Edit2: Here is a simple foo project illustrating the issue https://github.com/nurdyguy/ViewBagIssue

like image 223
nurdyguy Avatar asked Jan 23 '17 18:01

nurdyguy


People also ask

How do I get ViewBag data on my controller?

To pass the strongly typed data from Controller to View using ViewBag, we have to make a model class then populate its properties with some data and then pass that data to ViewBag with the help of a property. And then in the View, we can access the data of model class by using ViewBag with the pre-defined property.

Can we use ViewBag to pass data from view to controller?

Yes you cannot pass a Viewbag from view to controller. But you can pass them using TempData.

Does ViewBag require type casting?

ViewBag is a dynamic property that takes advantage of the new dynamic features in C# 4.0. ViewData requires typecasting for complex data type and check for null values to avoid error. ViewBag doesn't require typecasting for complex data type.

How dynamic is ViewBag?

The Microsoft Developer Network writes that the ViewBag property allows you to share values dynamically to the view from the controller. As such, it is considered a dynamic object without pre-set properties.


1 Answers

I still don't know why this is happening but here is a workaround I found. Create an OnActionExecuting filter:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace MyProj.Filters
{
    public class ViewBagFilter : IActionFilter
    {
        public void OnActionExecuting(ActionExecutingContext context)
        {
            // do something before the action executes
            var controller = context.Controller as Controller;
            controller.ViewBag.Title = "MyPage";
        }

        public void OnActionExecuted(ActionExecutedContext context)
        {
            // do something after the action executes
        }
    }
}

and add the following to the ConfigureServices method in Startup.cs:

services.AddMvc(options =>
{
    options.Filters.Add(typeof(ViewBagFilter));
    ... // you may have more here...
});

You'll notice the var controller = context.Controller as Controller; has a cast because the controller object on context is an object but it is easy enough to fix.

I'll post back here if I ever find out exactly what caused the issue to begin with. Good hunting!

like image 145
nurdyguy Avatar answered Oct 09 '22 05:10

nurdyguy