Asp.net mvc 4 主布局中是否可能有上下文相关的菜单?

Asp.net mvc 4 主布局中是否可能有上下文相关的菜单?,asp.net-mvc-4,Asp.net Mvc 4,我目前有一个名为_SubMenu.cshtml的共享文件,但这需要在我的所有视图中实现,我发现这很麻烦,而且可能不必要(?) 因此,我想知道在共享主布局文件中是否有一种“正确”的方法来实现上下文相关菜单,该菜单会根据RenderBody()中的渲染视图而变化 每个控制器应该处理这个问题,还是应该在其他地方处理这个问题?您可以使用子操作。其想法是让控制器执行如下操作: public class SomeController: Controller { [ChildActionOnly]

我目前有一个名为_SubMenu.cshtml的共享文件,但这需要在我的所有视图中实现,我发现这很麻烦,而且可能不必要(?)

因此,我想知道在共享主布局文件中是否有一种“正确”的方法来实现上下文相关菜单,该菜单会根据RenderBody()中的渲染视图而变化


每个控制器应该处理这个问题,还是应该在其他地方处理这个问题?

您可以使用子操作。其想法是让控制器执行如下操作:

public class SomeController: Controller
{
    [ChildActionOnly]
    public ActionResult SomeAction()
    {
        SomeViewModel model = ...
        return PartialView(model);
    }
}
然后您将获得相应的局部视图:

@model MyViewModel
...
可以包含在布局或视图中的:

@Html.Action("SomeAction", "SomeController")

菲尔·哈克在这里写了一篇关于儿童行为的博客:

你可以使用儿童行为。其想法是让控制器执行如下操作:

public class SomeController: Controller
{
    [ChildActionOnly]
    public ActionResult SomeAction()
    {
        SomeViewModel model = ...
        return PartialView(model);
    }
}
然后您将获得相应的局部视图:

@model MyViewModel
...
可以包含在布局或视图中的:

@Html.Action("SomeAction", "SomeController")

Phil Haack在这里写了一篇关于子操作的博客:

您可以创建一个特定于控制器的
\u子菜单.cshtml
,如下所示:

~/Views/Controller1/_SubMenu.cshtml
~/Views/Controller2/_SubMenu.cshtml
~/Views/Controller2/_SubMenu.cshtml
然后在您的
布局中

@Html.Partial("_SubMenu")
然后,视图引擎将根据当前控制器获取相应的
\u子菜单

或者,如果坚持使用单个
\u子菜单
partial,则可以
在当前控制器上切换
,并呈现适当的html:

<div id="menu">
    @switch (this.ViewContext.RouteData.Values["controller"].ToString().ToLower())
    {
        case "controller1":
            <a href="#">Controller 1 Action</a>
            <a href="#">Another Controller 1 Action</a>
            break;

        case "controller2":
            <a href="#">Controller 2 Action</a>
            <a href="#">Another Controller 2 Action</a>
            break;
    }
</div>

@开关(this.ViewContext.RouteData.Values[“controller”].ToString().ToLower())
{
案例“controller1”:
打破
案例“controller2”:
打破
}

您可以创建特定于控制器的
\u子菜单.cshtml
,如下所示:

~/Views/Controller1/_SubMenu.cshtml
~/Views/Controller2/_SubMenu.cshtml
~/Views/Controller2/_SubMenu.cshtml
然后在您的
布局中

@Html.Partial("_SubMenu")
然后,视图引擎将根据当前控制器获取相应的
\u子菜单

或者,如果坚持使用单个
\u子菜单
partial,则可以
在当前控制器上切换
,并呈现适当的html:

<div id="menu">
    @switch (this.ViewContext.RouteData.Values["controller"].ToString().ToLower())
    {
        case "controller1":
            <a href="#">Controller 1 Action</a>
            <a href="#">Another Controller 1 Action</a>
            break;

        case "controller2":
            <a href="#">Controller 2 Action</a>
            <a href="#">Another Controller 2 Action</a>
            break;
    }
</div>

@开关(this.ViewContext.RouteData.Values[“controller”].ToString().ToLower())
{
案例“controller1”:
打破
案例“controller2”:
打破
}

您还可以对特定的ViewData | | ViewBag值进行主/共享布局检查

@if(ViewData["_ContextMenuList_"] is List<ContextMenuItem>) {
       /// render the rest of the menu directly or in  a strongly typed partial view. 
}
然后,仅在控制器操作中设置该值,并用相关上下文数据填充该值

// Inside some controller action. 
//asuming some how you already got your client's info. 
        var contextMenu = new List<ContexMenuItem>();
        contextMenu.Add(new ContexMenuItem()
        {
            MenuText = "View More " + client.Name + "'s Info",
            Action = "ViewMore",
            Controller = "Clients",
            HtmlValues = null,
            RouteValues = new { id = client.ID }
        });
        contextMenu.Add(new ContexMenuItem()
        {
            MenuText = "Send a message to " + client.Name ,
            Action = "SendMessage",
            Controller = "Inbox",
            HtmlValues = null,
            RouteValues = new { id = client.ID }
        });

        ViewData["_ContextMenuList_"] = contextMenu;
//在某些控制器操作中。
//分析一下你是如何获得客户信息的。
var contextMenu=新列表();
添加(新的ContextMenuItem()
{
MenuText=“查看更多”+客户端名称+“'的信息”,
Action=“ViewMore”,
Controller=“Clients”,
HtmlValues=null,
RouteValues=new{id=client.id}
});
添加(新的ContextMenuItem()
{
MenuText=“向”+客户端名称发送消息,
Action=“SendMessage”,
Controller=“收件箱”,
HtmlValues=null,
RouteValues=new{id=client.id}
});
ViewData[“\u ContextMenuList”]=上下文菜单;
这可能很乏味,因为您必须在给定控制器上的所有相关操作中执行此操作。如果是这种情况,将代码重构为控制器内部的私有函数,并在应用时调用它


有些人可能会争辩说,这些数据应该总是在模型类上,在这种情况下,我认为这是一个上下文数据,而不一定是手头模型的一部分。通过简单地将渲染代码放在不了解模型的主类中,它还可以简化编码。它很像一些MVC模板上的_LogOnPartial.cshtml

您还可以对特定的ViewData | | ViewBag值进行主/共享布局检查

@if(ViewData["_ContextMenuList_"] is List<ContextMenuItem>) {
       /// render the rest of the menu directly or in  a strongly typed partial view. 
}
然后,仅在控制器操作中设置该值,并用相关上下文数据填充该值

// Inside some controller action. 
//asuming some how you already got your client's info. 
        var contextMenu = new List<ContexMenuItem>();
        contextMenu.Add(new ContexMenuItem()
        {
            MenuText = "View More " + client.Name + "'s Info",
            Action = "ViewMore",
            Controller = "Clients",
            HtmlValues = null,
            RouteValues = new { id = client.ID }
        });
        contextMenu.Add(new ContexMenuItem()
        {
            MenuText = "Send a message to " + client.Name ,
            Action = "SendMessage",
            Controller = "Inbox",
            HtmlValues = null,
            RouteValues = new { id = client.ID }
        });

        ViewData["_ContextMenuList_"] = contextMenu;
//在某些控制器操作中。
//分析一下你是如何获得客户信息的。
var contextMenu=新列表();
添加(新的ContextMenuItem()
{
MenuText=“查看更多”+客户端名称+“'的信息”,
Action=“ViewMore”,
Controller=“Clients”,
HtmlValues=null,
RouteValues=new{id=client.id}
});
添加(新的ContextMenuItem()
{
MenuText=“向”+客户端名称发送消息,
Action=“SendMessage”,
Controller=“收件箱”,
HtmlValues=null,
RouteValues=new{id=client.id}
});
ViewData[“\u ContextMenuList”]=上下文菜单;
这可能很乏味,因为您必须在给定控制器上的所有相关操作中执行此操作。如果是这种情况,将代码重构为控制器内部的私有函数,并在应用时调用它


有些人可能会争辩说,这些数据应该总是在模型类上,在这种情况下,我认为这是一个上下文数据,而不一定是手头模型的一部分。通过简单地将渲染代码放在不了解模型的主类中,它还可以简化编码。它很像一些MVC模板上的_LogOnPartial.cshtml

这和我现在做的不一样吗?对我来说,关键是要有一个共享的布局文件来维护,并且能够根据当前呈现的视图在需要时显示它。谢谢!你认为你在编辑的帖子中添加的最后一种方法是不好的练习吗?如果是的话,为什么?对我来说似乎更难维护(依赖于“魔法弦”,未来的控制器将需要修改层