Reputation: 427
I have a custom helper class to highlight the selected menu item,
<li class="nav-item">
@Html.MenuLink("Contact000", "Contact", "Home", new { @class = "nav-link" })
</li>
I want to use the helper htmlattributes and append to CSS if selected condition is true. I have seen a Similiar question but was not able to find a question using
var attrs = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
Here is my code
public static MvcHtmlString MenuLink(this HtmlHelper helper, string text, string action, string controller, object htmlAttributes)
{
var routeData = helper.ViewContext.RouteData.Values;
var currentController = routeData["controller"];
var currentAction = routeData["action"];
var attrs = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
if (String.Equals(action, currentAction as string,
StringComparison.OrdinalIgnoreCase)
&&
String.Equals(controller, currentController as string,
StringComparison.OrdinalIgnoreCase))
{
if (attrs.ContainsKey("class"))
{
attrs["class"] += " " + "currentMenuItem";
}
return helper.ActionLink(text, action, controller, attrs);
}
return helper.ActionLink(text, action, controller, htmlAttributes);
}
using
var attrs = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
I can append to the attributes.
when I return the helper.actionlink the attrs is not parsed correctly, below is the html generated,
<li class="nav-item">
<a Count="1" Keys="System.Collections.Generic.Dictionary`2+KeyCollection[System.String,System.Object]" Values="System.Collections.Generic.Dictionary`2+ValueCollection[System.String,System.Object]" href="/Home/Contact?Length=4">Contact000</a>
</li>
I am trying to get the following,
<li class="nav-item">
<a class="nav-link currentMenuItem" href="/Home/Contact">Contact000</a>
</li>
How do I convert attrs back into htmlAttributes for the helper to work ?
Upvotes: 3
Views: 2295
Reputation: 6551
You can create a RouteValueDictionary
using object htmlAttributes
. Then you can append a value like you would with any other IDictionary<TKey, TValue>
interface.
IDictionary<string, object> attrs = new RouteValueDictionary(htmlAttributes);
string key = "key";
string oldValue;
if (attrs.TryGetValue(key, out oldValue))
{
// append to value
attrs[key] = oldValue + "string to append";
}
else
{
// key not in attrs, handle accordingly
}
Full example:
using System.Web.Routing;
public static MvcHtmlString MenuLink(this HtmlHelper helper,
string text, string action, string controller, object htmlAttributes)
{
var routeData = helper.ViewContext.RouteData.Values;
var currentController = routeData["controller"];
var currentAction = routeData["action"];
IDictionary<string, object> attrs = new RouteValueDictionary(htmlAttributes);
if (String.Equals(action, currentAction as string,
StringComparison.OrdinalIgnoreCase)
&& String.Equals(controller, currentController as string,
StringComparison.OrdinalIgnoreCase))
{
string clazz;
if (attrs.TryGetValue("class", out clazz))
{
attrs["class"] = clazz + " " + "currentMenuItem";
}
// do you need to handle the case when there is no "class" attribute?
return helper.ActionLink(text, action, controller, attrs);
}
return helper.ActionLink(text, action, controller, htmlAttributes);
}
EDIT: I found the actual issue to your problem, you are using the wrong
Html.ActionLink
overload.
You are currently using the ActionLink(HtmlHelper, String, String, Object, Object)
overload, when you should be using the ActionLink(HtmlHelper, String, String, String, RouteValueDictionary, IDictionary<String, Object>)
overload.
helper.ActionLink(text, action, controller, routeValues: null, htmlAttributes: attrs);
Upvotes: 2