ASP.NET MVC 5 - Get current view's name (Razor .cshtml side)

Since you are using the convention where your page is named after the controller you can do this in razor to get the controller/page name:

@{
 var pageName = ViewContext.RouteData.Values["controller"].ToString()
}

<ul class="sidebar bg-grayDark">
    <li class="@(pageName == "Home" ? "active" : "")">
        <a href="@Url.Action("Index", "Home")">
            <span class="mif-home icon"></span>
            <span class="title">Home</span>
        </a>
    </li>
    <li class="bg-hover-black @(pageName == "Product" ? "active" : "")">
        <a href="@Url.Action("Index", "Product")">
            <span class="mif-shop icon"></span>
            <span class="title">Products</span>
            <span class="counter">14</span>
        </a>
    </li>
    <li class="bg-hover-black @(pageName == "Category" ? "active" : "")">
        <a href="@Url.Action("Index", "Category")">
            <span class="mif-flow-cascade icon"></span>
            <span class="title">Categories</span>
            <span class="counter">9</span>
        </a>
    </li>
    <li class="bg-hover-black @(pageName == "User" ? "active" : "")">
        <a href="@Url.Action("Index", "User")">
            <span class="mif-users icon"></span>
            <span class="title">Users</span>
            <span class="counter">1</span>
        </a>
    </li>
</ul>

This will set your active class on the page server side removing the need to do this client side with javascript.


Here is my approach for a cascaded Bootstrap dropdown submenu, decorated with active classes in the _layout.cshtml file of a Razor Pages project.

Major elements of this solution:

  • Get the current page route from ViewContext.RouteData.Values["page"].
  • Use Anchor Tag Helpers instead of @Url.Action().

Code:

<ul class="nav navbar-nav">
    @{
        String pageRoute = ViewContext.RouteData.Values["page"].ToString();
    }
    <li class="dropdown @( pageRoute.Contains("/CustomerModel/") ? "active" : "" )">
        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Customer-Model <span class="caret"></span></a>
        <ul class="dropdown-menu">
            <li class="@( pageRoute.Contains("/Customers/") ? "active" : "" )"><a asp-page="/CustomerModel/Customers/Index">Customers</a></li>
            <li class="@( pageRoute.Contains("/Partners/")  ? "active" : "" )"><a asp-page="/CustomerModel/CustomerPermissions/Index">CustomerPermissions</a></li>
        </ul>
    </li>
    <li class="dropdown @( pageRoute.Contains("/StaffModel/") ? "active" : "" )">
        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Staff-Model <span class="caret"></span></a>
        <ul class="dropdown-menu">
            <li class="@( pageRoute.Contains("/Staff/")              ? "active" : "" )"><a asp-page="/StaffModel/Staff/Index">Staff</a></li>
            <li class="@( pageRoute.Contains("/StaffGroups/")        ? "active" : "" )"><a asp-page="/StaffModel/StaffGroups/Index">StaffGroups</a></li>
            <li class="@( pageRoute.Contains("/PermissionsGroups/")  ? "active" : "" )"><a asp-page="/StaffModel/PermissionsGroups/Index">PermissionsGroups</a></li>
            <li class="@( pageRoute.Contains("/AllowedModules/")     ? "active" : "" )"><a asp-page="/StaffModel/AllowedModules/Index">AllowedModules</a></li>
            <li class="@( pageRoute.Contains("/AllowedServices/")    ? "active" : "" )"><a asp-page="/StaffModel/AllowedServices/Index">AllowedServices</a></li>
        </ul>
    </li>
</ul>

To confirm: You're changing the page when the user clicks on the item.

Because of this, your javascript will run, but then the whole page is re-written and you're back to the first state (ie with Home active as that's in the markup).

To check the current page, you can use location.href and compare it with the href url, something like:

$(function() {
    $("ul.sidebar>li").removeClass("active");  // or just not have active in the markup
    $("li>a[href=" + location.href + "]").closest("li").addClass("active");
});

Alternatively, and this would be more robust, you could pass a token (string, enum or const) in with the viewmodel and check that, eg:

<ul class='sidebar'>
    <li data-page='home'...
    ...
    <li data-page='categories'...

then

$(function() { 
    $("li[[email protected]]").addClass("active")

(or just in the markup...)

    <li data-page='categories' @(Model.PageName == 'Categories' ? "class=active" : "")>