使用控制器进行局部视图

Posted

技术标签:

【中文标题】使用控制器进行局部视图【英文标题】:Use Controller for Partial View 【发布时间】:2014-12-25 06:32:59 【问题描述】:

在企业级应用程序中,一切(嗯,几乎)都需要可配置。这就是我创建菜单和菜单项模型的原因,它允许管理员创建多个菜单:

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>

为了测试我当前的代码,我在布局视图中硬编码了一个菜单 ID:

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

现在,出现了几个问题,首先,我需要能够将菜单 ID 传递给部分,以便它能够呈现正确的菜单。通过使用局部视图方法,我不知道实现此目标的方法。其次,当我对正在加载的菜单应用安全性时,菜单项以相反的顺序显示。因此,通过使用某种类型的控制器来执行菜单和布局的数据逻辑,它应该可以解决这个问题。

那么,有人对我需要朝哪个方向提出任何建议吗?我开始认为我尝试对菜单使用部分视图(动态)是个坏主意?

【问题讨论】:

【参考方案1】:

除了直接调用@Html.Partial,您还可以拥有一个带有动作方法的控制器并使用@Html.RenderAction 代替@Html.Partial 方法。 在 action 方法中,您可以传递 id 并应用您需要的安全逻辑,并在视图中迭代菜单集合并显示所需的菜单。 这将使您的 UI 也保持整洁。

【讨论】:

我想我有它:@ Html.RenderAction("UserMenuAction", "Menu", new area = "Admin", id = 1 ); ,但现在我有一个问题。我正在根据页面的控制器和/或区域选择“活动”菜单项。现在,菜单总是返回管理区域,因为那是正在使用的控制器(ViewContext.RouteData.Values["Controller"].ToString()ViewContext.RouteData.DataTokens["area"])。有什么建议吗? 好吧,我认为您不能使用该逻辑来选择菜单项。您可能希望将所选菜单的状态添加为会话或添加到 ViewBag 并使用它来显示活动菜单项目。还有其他更好的方法可以做到这一点,但这取决于具体项目的组织方式。 我最终将区域、控制器和动作从 _Layout 传递到 UserMenuAction 中,效果很好!感谢您朝正确的方向轻推。

以上是关于使用控制器进行局部视图的主要内容,如果未能解决你的问题,请参考以下文章

从 MVC 中的控制器确定局部视图的模型

Sails js渲染局部视图

将局部变量从控制器传递到视图

获取模型/对象以在 .Net Core 的局部视图中使用

如何从 ASP.NET MVC 控制器的局部视图中读取值

从局部视图中对控制器的 AJAX 调用