Search code examples
asp.net-mvcrazorhtml-helper

ASP.NET MVC Razor Dynamic menu <li class='current'>


I have an HTML Menu that I render as a PartialView in my Shared Layout.cshtml and has the following structure:

I call the menu in my Layout.cshtml like this:

 @Html.Action("LeftMenu", "Common", new { context = ViewContext})

This is the left menu structure:

<li class='current'>
   <a class='current' href="@Url.Action("Index","Home")">
   <span class="badge pull-right">17</span>
   <i class="icon-dashboard"></i> Dashboard
   </a>
</li>
<li>
   <a href="@Url.Action("Absence","Incident")" class="is-dropdown-menu">
   <span class="badge pull-right"></span>
   <i class="icon-bar-chart"></i> Absence List
   </a>
   <ul>
      <li>
         <a href="@Url.Action("AbsenceList","Incident")">
         <i class="icon-random"></i>
         Notice List
         </a>
      </li>
      <li>
         <a href="@Url.Action("NewAbsence","Incident")">
         <i class="icon-bullseye"></i>
         New Notice
         </a>
      </li>
   </ul>
</li>

And I want to make my links dynamic to depending on the current View I can activate the <li> element by assigning the class='current' and also to the <a href> element.

I saw that I can do that using a HTML Helper:

public static MvcHtmlString MenuItem(
        this HtmlHelper htmlHelper, 
        string text,
        string action, 
        string controller
    )
    {
        var li = new TagBuilder("li");
        var routeData = htmlHelper.ViewContext.RouteData;
        var currentAction = routeData.GetRequiredString("action");
        var currentController = routeData.GetRequiredString("controller");
        if (string.Equals(currentAction, action, StringComparison.OrdinalIgnoreCase) &&
            string.Equals(currentController, controller, StringComparison.OrdinalIgnoreCase))
        {
            li.AddCssClass("active");
        }
        li.InnerHtml = htmlHelper.ActionLink(text, action, controller).ToHtmlString();
        return MvcHtmlString.Create(li.ToString());
    }

But the above code I don't think It will help me create the exact <li> structure that my menu requires in order to look nice.

enter image description here

If I Inspect (google chrome) my active menu element what I get is this:

enter image description here

Any help is well appreciated.


Solution

  • I typically do something like the following:

    @{ string url; }
    <ul>
        @{ url = Url.Action("SomeAction", "SomeController"); }
        <li>
            <a class="@(url == Request.Url.AbsolutePath ? "current" : string.Empty)" href="@url">
                Some Action
            </a>
        </li>
    
        @{ url = Url.Action("SomeOtherAction", "SomeOtherController"); }
        <li>
            <a class="@(url == Request.Url.AbsolutePath ? "current" : string.Empty)" href="@url">
                Some Other Action
            </a>
        </li>
    
        ...
    

    In other words, in each case, you compare the URL for the link with the currently requested URL and render the class when it matches.