How can I create a global menu for my application

2019-07-31 18:53发布

I need to put couple drop down menus on the upper right hand side of my application. These menus need to appears on every page where that layout is used.

The only problem is that items of the menu are pulled from a database.

Usually I would pass the list to the model like so

public ActionResult Clients()
{
   using (SomeContext db = new SomeContext())
   {
       var clients = db.Database.SqlQuery<Client>("SELECT * FROM clients").ToList();

       return View(clients);
   }
}

But, I am not sure how to do the same thing without having to write the same code for every view. I want to only write this code below once and not worry about having to write the same code for every view.

What is the right way to have a global drop down menu for my application?

2条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-07-31 19:19

I prefer to use an controller to render my menu. This provides caching, reuse and logic for a menu (like showing or not showing a menu based on roles/claims). You can read the complete article by Phil Haacked - Html.RenderAction and Html.Action, excerpt below.

c#

public class MenusController {
  [ChildActionOnly]
  public ActionResult MainMenu() {
    var menu = GetMenuFromSomewhere();
   return PartialView(menu);
  }
}

Html:

<html>
<head><title></title></head>
<body>
  @Html.Action("MainMenu", "Menus")
  <h1>Welcome to the Index View</h1>
</body>
</html>
查看更多
贪生不怕死
3楼-- · 2019-07-31 19:41

You can create an action filter to do this.

public class LoadMenu : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var vb = filterContext.Controller.ViewBag;
        var menu = new List<MenuItem>();
        //I am hard coding to 2 items here. You may read it from your db table
        menu.Add(new MenuItem() { Text = "Home", TargetUrl = "Home/Index" });
        menu.Add(new MenuItem() { Text = "Careers", TargetUrl = "Home/Careers" });
        vb.Menus = menu;
    }
}

Assuming you have a class called MenuItem

public class MenuItem
{
    public string Text { set; get; }
    public string TargetUrl { set; get; }

    public List<MenuItem> Childs { set; get; }

    public MenuItem()
    {
        this.Childs = new List<MenuItem>();
    }
}

Now, if you want this in every page, just register it globally. You can do this in the RegisterRoutes method in RouteConfig class

public static void RegisterRoutes(RouteCollection routes)
{
  //Existing route definitions goes here

   GlobalFilters.Filters.Add(new LoadMenu());
}

Now in your Layout file, read the ViewBag item called Menus and build the menu markup as needed.

@{
    var menu = ViewBag.Menus as List<MenuItem>;
    if (menu != null)
    {
        foreach (var m in menu)
        {
            <li><a href="@m.TargetUrl">@m.Text</a></li>
        }
    }
}

You may update the above code to render Childs as needed.

查看更多
登录 后发表回答