The best way to handle your situation is with a child action. You simply create an action in some controller in your project. Since this deals with user-level access, I'll use AccountController
.
[AllowAnonymous]
[ChildActionOnly]
public ActionResult UserMenu()
{
if (User.Identity.IsAuthenticated())
{
// logic to select your menu from database
return View(menu);
}
// optionally you can return a different menu for anonymous users here
return Content("");
}
Then, you create the UserMenu.cshtml
view in your Views\Account
directory. In this view, you'll simply use the model instance you passed in (menu
above) to render just portion of your site navigation the menu
object applies to.
Finally, in your layout, wherever you want this menu to appear, call:
@Html.Action("UserMenu", "Account");
If you want to only have this run once (really better put as "occasionally"), then you can utilize caching. Just add the following additional attribute to your child action:
[OutputCache(Duration = 3600, VaryByCustom = "User")]
There's no built in way to vary the cache by a particular user, so you have to create a custom vary. It's relatively easy though. Just add something like the following to Global.asax:
public override string GetVaryByCustomString(HttpContext context, string arg)
{
if(arg.ToLower() == "user")
{
if (context.User.Identity.IsAuthenticated())
{
return context.User.Identity.Name;
}
return null;
}
return base.GetVaryByCustomString(context, arg);
}
Then, MVC will cache the output of the UserMenu
action for each unique user for 1 hour (3600 seconds), meaning any other requests by the same user will not invoke the action or send any queries to your database until the cache has expired.