如何从我的应用程序创建一个全局菜单,其中的项目是从数据库中提取的?

时间:2016-07-22 15:58:44

标签: c# asp.net-mvc razor

我需要在我的应用程序的右上角放置几个下拉菜单。这些菜单需要出现在使用该布局的每个页面上。

唯一的问题是菜单的项目是从数据库中提取的。

通常我会将列表传递给模型,如此

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

       return View(clients);
   }
}

但是,我不知道如何在不必为每个视图编写相同代码的情况下执行相同的操作。我想只编写下面这段代码一次,不用担心必须为每个视图编写相同的代码。

为我的应用程序提供全局下拉菜单的正确方法是什么?

2 个答案:

答案 0 :(得分:2)

我更喜欢使用控制器来渲染我的菜单。这为菜单提供了缓存,重用和逻辑(如显示或不显示基于角色/声明的菜单)。您可以阅读Phil Haacked - Html.RenderAction and Html.Action的完整文章,摘录如下。

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>

答案 1 :(得分:1)

您可以创建一个动作过滤器来执行此操作。

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;
    }
}

假设您有一个名为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>();
    }
}

现在,如果您想在每个页面中使用它,只需在全局注册即可。您可以在RegisterRoutes

中的RouteConfig方法中执行此操作
public static void RegisterRoutes(RouteCollection routes)
{
  //Existing route definitions goes here

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

现在在您的布局文件中,阅读名为Menus的ViewBag项,并根据需要构建菜单标记。

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

您可以根据需要更新上述代码以呈现Childs