Use a shared controller class for entire area?
Solution 1
For something like a menu that should be repeated throughout a particular area, you want to use a child action:
[ChildActionOnly]
public ActionResult AdminMenu()
{
var menu = _db.Menus.Include("MenuItems").First(m => m.Name == "Admin menu");
var model = new MenuModelView
{
Name = menu.Name,
CssClass = menu.CssClass,
CssId = menu.CssId,
Deleted = menu.Deleted,
MenuItems = menu.MenuItems
};
return PartialView("_AdminMenu", model);
}
I changed your code around a bit so that you actually pass your view model to the view instead of stuffing it in ViewBag
. Don't use ViewBag
. It's awful.
_AdminMenu.cshtml
@model Namespace.To.MenuModelView
<!-- render your menu and just your menu here -->
Areas\Admin\Views\Shared\_Layout.cshtml
...
<!-- place this where you want the menu to appear in your layout -->
@Html.Action("AdminMenu", "ControllerNameWhereChildActionExists")
...
Solution 2
Yes, you can... you can use inheritance to create what is effectively a shared controller class. Like so...
Public Class AdminBaseController : Controller {
public ActionResult Index()
{
var model = _db.Menus.Include("MenuItems").First(m => m.Name == "Admin menu");
ViewBag.AdminMenu = new MenuModelView
{
Name = model.Name,
CssClass = model.CssClass,
CssId = model.CssId,
Deleted = model.Deleted,
MenuItems = model.MenuItems
};
return View();
}
}
Then you can build all of your other controllers to inherit it, like so:
Public Class AdminController1 : AdminBaseController
Related videos on Youtube

Floris
Updated on November 27, 2022Comments
-
Floris 26 days
I've got a area "Admin" on my mvc application with for each page it's own controller. Like PageController and ModuleController etc. On my shared layout file (View/_Shared/_LayoutAdmin.chtml) the menu gets loaded dynamicly into a @model var. Now in my HomeController I have this method the fetch the menu:
public ActionResult Index() { var model = _db.Menus.Include("MenuItems").First(m => m.Name == "Admin menu"); ViewBag.AdminMenu = new MenuModelView { Name = model.Name, CssClass = model.CssClass, CssId = model.CssId, Deleted = model.Deleted, MenuItems = model.MenuItems }; return View(); }
This block of code is needed on every controller class. I don't think duplicating this code is the best idea. So I was wondering if it is possible to have this method in a shared controller class for the entire Admin area. Like a code behind class for the Shared/_LayoutAdmin.chtml file.
-
Floris about 8 yearsThis works, thanks. I ended up fetching the menu from the constructor in the AdminBaseController class.
-
Chris Pratt about 8 yearsWhile this is a perfectly valid answer, it's not ideal to rely on all your controllers inheriting from a base controller in order for something like a menu to show on the page. If you forget or a new developer comes along that doesn't know that every controller must inherit from this base controller, then all of a sudden the menu is gone with no obvious reason why. Using a child action is preferable as it just works, no matter what your controller inherits from.
-
Floris about 8 yearsBut this child action needs to be copied to all controllers within the admin area. That's a lot of duplicate code, not sure if that's what we want.
-
Chris Pratt about 8 yearsNot at all. You just need to put it in one controller, and the call that partucular action and controller in your layout. No duplicate code at all.