Best way to wire up database-driven menu in ASP.NET MVC

☆樱花仙子☆ 提交于 2019-12-03 08:51:57

问题


I'm looking for a way to handle a database-driven menu in ASP.NET MVC that doesn't violate the MVC principles. I want to replace the hard-coded, default, "Home, About" menu with something from my database. How would I wire this up? Would I just set up a ContentPlaceHolder in my Site.Master and have regenerated in my Views? That doesn't seem right to me.


回答1:


My main menu is a ViewUserControl that is rendered as a partial view in my MasterPage. Although mine is hard-coded, you could easily generate it from ViewData. Generating it from view data would probably involve implementing either a custom FilterAttribute that specified the parameters to use in generating the menu that would be applied to each controller/action or, if the menu is the same on each page, implementing a base controller that fills in the view data by overriding OnActionExecuted and adding to the ViewData in it.

Example (note, you'd probably use caching for the results instead of getting them from the db each time).

Model classes

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 : of type 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>

MasterPage

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


来源:https://stackoverflow.com/questions/723994/best-way-to-wire-up-database-driven-menu-in-asp-net-mvc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!