I have created ASP.NET Core application and now I'm trying to use ViewBag in _LoginPartial. I have created base controller:
public class BaseController : Controller
{
public ApplicationDbContext _db;
public BaseController(ApplicationDbContext db)
{
_db = db;
ViewData["MyKey"] = _db.MyTable.ToList();
}
}
All my controllers derive from this BaseController.
But when I see ViewData in _LoginPartial.cshtml, I can only see that it contains default Key=Title, Value=Home Page. What should I do to have MyKey available in _LoginPartial?
Thanks!
The problem is that you are trying to set ViewData
content within the controller’s constructor.
The ViewData
dictionary is not actually created by the controller. It is created at a very different point within the MVC pipeline and then gets injected into the controller. You can basically see this process as something like this:
// create controller
var controller = CreateController<MyController>();
// do stuff
// inject ViewData
controller.ViewData = GetViewDataDictionary();
// invoke controller action
var result = controller.SomeAction();
So the ViewData
gets provided after the controller has been created; after its constructor ran. So any assignments to the view data within the constructor will not apply to the actual view data dictionary.
As such, you will need to set those values at a different time, you cannot use the constructor there. Using the ViewData
in general is somewhat legacy construct that you should try to avoid if possible. Instead, you should work with strongly typed view model objects. Of course, this will require you to pass the data explicitly in each action, but that way you are also not introducing any implicit data flow.
An alternative, which is especially useful if what you are doing should actually always apply to the _LoginPartial
, would be to use a view component. View components are reusable components that you can use inside of your views, which will behave similarly to a controller action. So you could just insert a view component into your partial, and have that run the logic (asynchronously even!) to provide the data from your database. And you wouldn’t need to mess with any of your controllers to make it work.