As a base for discussion. Create a standard ASP.NET MVC Web project.
It will contain two menu items in the master page:
<script type="javascript/text">
$( document ).ready( function() {
@if (Request.Url.AbsolutePath.ToLower() == "/")
{
@Html.Raw("$('.navbar-nav li').eq(0).attr('class','active');")
}
@if (Request.Url.AbsolutePath.ToLower().Contains("details"))
{
@Html.Raw("$('.navbar-nav li').eq(1).attr('class','active');")
}
@if (Request.Url.AbsolutePath.ToLower().Contains("schedule"))
{
@Html.Raw("$('.navbar-nav li').eq(2).attr('class','active');")
}
});
</script>
Chucked this together in 5mins, I could probably refactor it, but should give you the basic idea, its probably most useful for smaller sites.
If you are using T4MVC, you can use this:
public static HtmlString MenuLink(
this HtmlHelper helper,
string text,
IT4MVCActionResult action,
object htmlAttributes = null)
{
var currentController = helper.ViewContext.RouteData.Values["controller"] as string ?? "home";
var currentAction = helper.ViewContext.RouteData.Values["action"] as string ?? "index";
var attributes = new RouteValueDictionary(htmlAttributes);
var cssClass = (attributes.ContainsKey("class"))
? attributes["class"] + " "
: string.Empty;
string selectedClass;
if(action.Controller.Equals(currentController, StringComparison.InvariantCultureIgnoreCase)
{
selectedClass = "selected-parent";
if(action.Action.Equals(currentAction, StringComparison.InvariantCultureIgnoreCase))
selectedClass = "selected";
}
cssClass += selectedClass;
attributes["class"] = cssClass;
return helper.ActionLink(text, (ActionResult)action, attributes);
}
I recently created an HTML Helper for this that looks like:
public static string NavigationLink(this HtmlHelper helper, string path, string text)
{
string cssClass = String.Empty;
if (HttpContext.Current.Request.Path.IndexOf(path) != -1)
{
cssClass = "class = 'selected'";
}
return String.Format(@"<li><a href='{0}' {1}>{2}</a></li>", path, cssClass, text);
}
The Implementation looks like this:
<ul id="Navigation">
<%=Html.NavigationLink("/Path1", "Text1")%>
<%=Html.NavigationLink("/Path2", "Text2")%>
<%=Html.NavigationLink("/Path3", "Text3")%>
<%=Html.NavigationLink("/Path4", "Text4")%>
</ul>
It might just be that it's the 5th parameter, so slot a null before your html attribute. This post here describes it as such, though you can pass in some stuff on the 4th arguement, the 5th is specifically for HTMLattributes
The easiest way is to get the current controller and action from the ViewContext's RouteData. Note the change in signature and use of @ to escape the keyword.
<% var controller = ViewContext.RouteData.Values["controller"] as string ?? "Home";
var action = ViewContext.RouteData.Values["action"] as string ?? "Index";
var page = (controller + ":" + action).ToLower();
%>
<%= Html.ActionLink( "About", "About", "Home", null,
new { @class = page == "home:about" ? "current" : "" ) %>
<%= Html.ActionLink( "Home", "Index", "Home", null,
new { @class = page == "home:index" ? "current" : "" ) %>
Note that you could combine this an HtmlHelper extension like @Jon's and make it cleaner.
<%= Html.MenuLink( "About", "About", "Home", null, null, "current" ) %>
Where MenuActionLink is
public static class MenuHelperExtensions
{
public static string MenuLink( this HtmlHelper helper,
string text,
string action,
string controller,
object routeValues,
object htmlAttributes,
string currentClass )
{
RouteValueDictionary attributes = new RouteValueDictionary( htmlAttributes );
string currentController = helper.ViewContext.RouteData.Values["controller"] as string ?? "home";
string currentAction = helper.ViewContext.RouteData.Values["action"] as string ?? "index";
string page = string.Format( "{0}:{1}", currentController, currentAction ).ToLower();
string thisPage = string.Format( "{0}:{1}", controller, action ).ToLower();
attributes["class"] = (page == thisPage) ? currentClass : "";
return helper.ActionLink( text, action, controller, new RouteValueDictionary( routeValues ), attributes );
}
}