如何在布局中显示内容

How to show something in Layout

我有一个标准的 ASP.NET MVC 应用程序,带有布局页面和许多视图。例如,对于某些用户(取决于他们的属性或其他原因)我想显示一些东西(即附加菜单)。

布局页面:

@if (Request.IsAuthenticated && User.IsInRole("Admin"))
{
    <li class="dropdown">
        <a aria-expanded="false" class="dropdown-toggle" role="button" href="#" data-toggle="dropdown">Admin <span class="caret"></span></a>
        <ul class="dropdown-menu" role="menu">
            <li>@Html.ActionLink("Users", "Index", "User")</li>
            /* ............ */
        </ul>
    </li>
}
else if (SomeParameter == "SomeValue") // I WANT TO HAVE THIS VARIABLE FOR ALL PAGES
{
/* ............ */
}

如何实现?当然可以:

  1. 向每个方法添加类似 ViewTag.SomeParameter = "SomeValue" 的内容。但我认为没有必要描述为什么这种方法不好
  2. 添加到每个控制器方法:

    protected override void Initialize(System.Web.Routing.RequestContext requestContext)
    {
        base.Initialize(requestContext);
        ViewTag.SomeParameter = "SomeValue";
    }
    

这个方法也不好,尤其是当我们有10个以上的控制器时,这些控制器的视图都使用这个Layout。

哪种方法好?

实施基本视图模型。让所有相关的视图模型都继承自基础。将布局的模型指定为基础视图模型。我将使用布尔值,但您可以使用字符串。

ViewModel

public class BaseViewModel
{
    public bool CanSeeSecondaryMenu {get;set;}
}

布局

@model Web.BaseViewModel

...
else if (Model.CanSeeSecondaryMenu) // I WANT TO HAVE THIS VARIABLE FOR ALL PAGES
{
    /* ............ */
}

动作

public ActionResult Index()
{
    var model = new InheritedFromBaseViewModel { CanSeeSecondaryMenu = //Set via logic };
    return View(model);
}

如果您想概括设置此布尔值的逻辑,您可以创建一个基本控制器,让所有相关控制器继承它,并覆盖 OnActionExecuting 方法

public abstract class BaseController : Controller
{
    protected bool CanSeeSecondaryMenu { get; set; }

    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        base.OnActionExecuting(filterContext);
        CanSeeSecondaryMenu = //Set via logic
    }
}

然后 Index 动作会变成这样...

public ActionResult Index()
{
    var model = new InheritedFromBaseViewModel { CanSeeSecondaryMenu = CanSeeSecondaryMenu };
    return View(model);
}