在ASP.NET MVC中连接数据库驱动菜单的最佳方法

时间:2009-04-07 02:42:59

标签: asp.net-mvc linq-to-sql .net-3.5 master-pages

我正在寻找一种方法来处理ASP.NET MVC中不违反MVC原则的数据库驱动菜单。我想用我的数据库中的东西替换硬编码的默认“Home,About”菜单。我该如何连线?我会在Site.Master中设置一个ContentPlaceHolder并在我的视图中重新生成吗?这对我来说似乎不对。

1 个答案:

答案 0 :(得分:2)

我的主菜单是一个ViewUserControl,它在我的MasterPage中呈现为部分视图。尽管我的是硬编码的,但您可以从ViewData轻松生成它。从视图数据生成它可能涉及实现自定义FilterAttribute,该自定义FilterAttribute指定用于生成将应用于每个控制器/操作的菜单的参数,或者,如果每个页面上的菜单相同,则实现填充的基本控制器在视图数据中,通过重写OnActionExecuted并添加到其中的ViewData。

示例(注意,您可能会使用缓存来获取结果,而不是每次都从数据库中获取它们。)

模型类

public class MenuItem
{
    public string Text { get; set; }
    public string Action { get; set; }
    public string Controller { get; set; }
}

public class Menu
{
     public string Heading { get; set; }
     public IEnumerable<MenuItem> Items { get; set; }
}

MenuControl.ascx:类型System.Web.Mvc.ViewPage<List<Menu>>

<div id="mainMenu">
<% foreach (var menu in Model) { %>
   <div class="menu">
      <h2 class="menu-heading"><%= menu.Heading %></h2>
      <% foreach (var item in Model.Items) { %>
         <%= Html.ActionLink( item.Text,
                              item.Action,
                              item.Controller,
                              null,
                              { @class = "menu-item" } ) %>
      <% } %>
   </div>
<% } %>
</div>

母版

<html>
<head>
...
<asp:ContentPlaceHolder runat="server" id="HeaderContent">
</head>
<body>

... other HTML...

<% Html.RenderPartial( "MenuControl", ViewData["mainMenu"], ViewData ); %>

<asp:ContentPlaceHolder runat="server" id="BodyContent" />

... more HTML ...

</body>
</html>

BaseController

public override void OnActionExecuted( ActionExecutedContext filterContext )
{
     if (filterContext != null)
     {
         var context = filterContext.Result as ViewResult;
         if (context != null) {
             context.ViewData["mainMenu"] = 
                 db.MenuData.Where( m => m.Type == "mainMenu" )
                            .Select( m => new Menu {
                                Heading = m.Heading,
                                Items = db.ItemData.Where( i => i.MenuID == m.MenuID )
                                               .OrderBy( i => i.Name )
                                               .Select( i => new MenuItem {
                                                   Text = i.Text,
                                                   Action = i.Operation,
                                                   Controller = i.Table
                                               })
                            });
         }
    }
}