如何为ASP.NET MCV控制器中的所有操作设置viewbag值

时间:2016-04-15 13:48:19

标签: c# asp.net asp.net-mvc

我正在尝试实现动态菜单。我已经创建了一个基本控制器(class PortalController : Controller)我已经为这个类添加了一些虚拟方法。其中一种方法是为站点菜单生成html。这允许我写一次并在需要时覆盖它。问题是直接从视图中调用方法是不好的做法。

我希望能够使用此方法创建一个包含主菜单html的viewbag字符串。我在这里遇到的问题是所有方法都需要在返回视图之前调用此generateMenu()方法。它是一个解决方案,但我不喜欢它。是否有更简洁的方法在对象级别执行此操作。默认情况下,任何继承“PortalController”的对象都会自动在viewbag变量中包含菜单字符串。我怎么能这样做?

到目前为止,我写过这篇文章。我真正喜欢的几乎相当于一个构造函数。构造对象时将生成菜单。使用以下方法仅在调用视图时呈现菜单。我需要控制器中的多个动作才能在菜单中包含不同的项目。

protected override ViewResult View(IView view, object model)
{
    ViewBag.Menu = this.GenerateMenu();
    return base.View(view, model);
}

3 个答案:

答案 0 :(得分:1)

您可以在PortalController的所有视图中使用Html.Partial生成此菜单,并将一些对象作为此视图的模型传递(如果需要)

@model Foo

@Html.Partial("menu", Foo)

/* rest of the page */
<form>

</form>

答案 1 :(得分:0)

您是否有义务在控制器中生成菜单html? 我认为这是一个不好的例子。 您可以从基本菜单开始并使用css对其进行操作。 菜单必须位于布局页面中,或者位于部分视图中,该视图将在其他相关视图中调用。

<div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li>@Html.ActionLink("About", "About", "Home")</li>
                    <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                 </ul>
                @Html.Partial("_LoginPartial")
 </div>

使用jquery css显示动态显示菜单或使用控制器操作中的角色隐藏。 您可以使用调用ajax来显示菜单。

答案 2 :(得分:0)

如果您正在动态构建菜单项(来自db等),您可以创建一个可以从布局文件中调用的操作方法。

public ActionResult RenderMenu()
{
  // Build the data needed to render the menu. Pass to the view

    var menu = new List<MenuItem>
    {
        new MenuItem(){
            Text = "Home",
            Childs = new List<MenuItem>
            {
                new MenuItem {Text = "About"}
            }
        }
    };
  return PartialView(menuItems);
}

假设你有一个像这样的MenuItem类

public class MenuItem
{
    public string Text { set; get; }
    public string TargetUrl { set; get; }
    public List<MenuItem> Childs { set; get; }
    public MenuItem()
    {
        this.Childs=new List<MenuItem>();
    }
}

并且在您的视图中,您将使用它来呈现您想要的菜单项。

要在所有页面中包含此菜单,只需在布局

中调用Html.Action方法即可
@Html.Action("RenderMenu","ControllerName")

或者,如果您想为所有请求设置要查看的内容,可以创建一个动作过滤器来执行此操作。

public class LoadMenu : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var vb = filterContext.Controller.ViewBag; 
        vb.Menu = "Some string you want";
    }
}

并将其注册为Global.asax.cs的Application_Start事件中的全局过滤器。

GlobalFilters.Filters.Add(new LoadMenu());