В приложении корпоративного уровня все (ну, почти) должно быть настраиваемым. Вот почему я создал модель меню и элементов меню, которая позволит администратору создавать несколько меню:
public class Menu
{
[Key]
public int ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public virtual ICollection<MenuItem> MenuItems { get; set; }
}
public class MenuItem
{
[Key]
public int ID { get; set; }
public int? MenuID { get; set; }
public int? ParentMenuItemID { get; set; }
public virtual IdentityRole Role { get; set; }
public string Name { get; set; }
public string Area { get; set; }
public string Controller { get; set; }
public string Action { get; set; }
public string Url { get; set; }
public string CssClass { get; set; }
public string Icon { get; set; }
public virtual ICollection<MenuItem> MenuItems { get; set; }
public virtual Menu Menu { get; set; }
}
Я пытаюсь дать им возможность отображать конкретное меню в частичном представлении, которое будет отображаться в представлении макета, и применяется безопасность:
<ul>
<li>
<div class="sidebar-toggler hidden-phone"></div>
</li>
<li>
<form class="sidebar-search">
<div class="input-box">
<a href="javascript:;" class="remove"></a>
<input type="text" placeholder="Search..." />
<input type="button" class="submit" value=" " />
</div>
</form>
</li>
@foreach (var m in Model.MenuItems)
{
if (m.Role == null || User.IsInRole(m.Role.Name))
{
<li class="@(m.MenuItems != null && m.MenuItems.Count > 0 ? "has-sub " : "") @(ViewContext.RouteData.Values["Controller"].ToString() == m.Controller || (ViewContext.RouteData.DataTokens["area"] != null && ViewContext.RouteData.DataTokens["area"].ToString() == m.Area) ? "active " : " ") ">
<a href="@Url.Action(m.Action, m.Controller, new { area = (string.IsNullOrEmpty(m.Area) ? "" : m.Area) }, null)">
@if (!string.IsNullOrEmpty(m.Icon))
{
<i class="@m.Icon"></i>
}
<span class="title">@m.Name</span>
@if (ViewContext.RouteData.Values["Controller"].ToString() == m.Controller || (ViewContext.RouteData.DataTokens["area"] != null && ViewContext.RouteData.DataTokens["area"].ToString() == m.Area))
{
<span class="selected"></span>
}
</a>
@if (m.MenuItems != null && m.MenuItems.Count > 0)
{
<ul class="sub">
@foreach (var mi in m.MenuItems)
{
if (mi.Role == null || User.IsInRole(mi.Role.Name))
{
<li class="@(ViewBag.Title == mi.Name ? "active" : "")">
<a href="@Url.Action(mi.Action, mi.Controller, new { area = mi.Area })">@mi.Name</a>
</li>
}
}
</ul>
}
</li>
}
}
</ul>
Чтобы протестировать мой текущий код, я жестко запрограммировал идентификатор меню в представлении макета:
<div class="page-container row-fluid">
<div class="page-sidebar nav-collapse collapse">
@Html.Partial("_LeftMenu", new MyAppContext().Menus.Find(1))
</div>
<div class="page-content">
@RenderBody()
</div>
</div>
Теперь возникла пара проблем. Во-первых, мне нужно передать идентификатор меню партиалу, чтобы он отображал правильное меню. Используя метод частичного просмотра, я не знаю, как достичь этой цели. Во-вторых, когда я применил защиту к загружаемому меню, пункты меню отображаются в обратном порядке. Таким образом, наличие контроллера некоторого типа для выполнения логики данных для меню и макета должно решить эту проблему.
Итак, у кого-нибудь есть какие-либо предложения относительно того, в каком направлении мне нужно двигаться? Я начинаю думать, что моя попытка использовать частичное представление меню (будучи динамическим) — плохая идея?