Oleg Sh
Oleg Sh

Reputation: 9013

How to show something in Layout

I have a standard ASP.NET MVC application, with Layout page and many views. For example, for some users (depend on their properties or by another reason) I want to show something (i.e. additional menu).

Layout page:

@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
{
/* ............ */
}

How to implement it? Of course, I can:

  1. add something like ViewTag.SomeParameter = "SomeValue" to each method. But I think not necessary to describe why this approach is bad
  2. add to each controller method:

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

This method is bad also, especially if we have 10+ controllers, views of these controllers use this Layout.

Which approach is good?

Upvotes: 0

Views: 104

Answers (1)

jimSampica
jimSampica

Reputation: 12410

Implement a base viewmodel. Have all relevant viewmodels inherit from the base. Specify the layout's model as the base viewmodel. I'll use a boolean but you can use a string.

ViewModel

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

Layout

@model Web.BaseViewModel

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

Action

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

If you want to generalize the logic for setting this boolean value you can create a base controller, have all relevant controllers inherit from it, and override the OnActionExecuting method

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

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

Then the Index action would change to this...

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

Upvotes: 2

Related Questions