The best way to connect to a database in an ASP.NET MVC menu

I am looking for a way to handle a database driven menu in ASP.NET MVC that does not violate MVC principles. I want to replace the default hardcoded menu "Home, About" with something from my database. How can I do it? Can I customize ContentPlaceHolder on my Site.Master and updated in my views? This does not seem right to me.

+3
source share
1 answer

My main menu is ViewUserControl, which appears as a partial view in my MasterPage. Although mine is hardcoded, you can easily create it from ViewData. Its generation from view data is probably related to the implementation of either the FilterAttribute custom attribute, which sets the parameters that will be used to create the menu that will be applied to each controller / action, or, if the menu is the same on each page, the basic controller is implemented, which fills in the data view, overriding OnActionExecuted and adding ViewData to it.

Example (note that you are likely to use caching for results instead of getting them from db every time).

Class Models

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: 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
                                               })
                            });
         }
    }
}
+2

Source: https://habr.com/ru/post/1706014/


All Articles