TagBuilder.MergeAttributes not working properly

I am trying to create an HtmlHelper and I need to allow users to add their own custom attributes to the html tag.

I tried to do this using the TagBuilder class, but it seems that instead of merging the attributes, it just replaces them.

This is what I did in C #:

public static MvcHtmlString List(HtmlHelper helper, object htmlAttributes) { var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes); var tag = new TagBuilder("div"); tag.AddCssClass("myClass"); tag.MergeAttributes(attributes, false); // tag class property has value "myClass", not "myClass testClass" return new MvcHtmlString("<div>"); } 

It's my opinion:

 @Html.List(new { @class = "testClass" }) 

What am I doing wrong?

+8
c # asp.net-mvc html-helper
source share
3 answers

The TagBuilder.MergeAttributes method TagBuilder.MergeAttributes not work as you expect. This is the exact code for this method:

  public void MergeAttributes<TKey, TValue>(IDictionary<TKey, TValue> attributes, bool replaceExisting) { if (attributes != null) { foreach (var entry in attributes) { string key = Convert.ToString(entry.Key, CultureInfo.InvariantCulture); string value = Convert.ToString(entry.Value, CultureInfo.InvariantCulture); MergeAttribute(key, value, replaceExisting); } } } public void MergeAttribute(string key, string value, bool replaceExisting) { if (String.IsNullOrEmpty(key)) { throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "key"); } if (replaceExisting || !Attributes.ContainsKey(key)) { Attributes[key] = value; } } 

As you can see, it adds new attributes to the collection (if replaceExisting set to true, it also replaces those that are already collected). It does not execute and does not bind merge logic values. If you want to combine values, you need to do it yourself:

 public static MvcHtmlString List(this HtmlHelperhelper, object htmlAttributes) { var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes); if (attributes.ContainsKey("class")) attributes["class"] = "myclass " + attributes["class"]; else attributes.Add("class", "myClass"); var tag = new TagBuilder("div"); tag.MergeAttributes(attributes, false); return new MvcHtmlString(tag.ToString(TagRenderMode.Normal)); } 
+16
source share

MergeAttributes overrides the attributes already in the tag, AddCssClass adds the name to the class value.

So, just switch it and it will work;

  tag.MergeAttributes(attributes, false); tag.AddCssClass("myClass"); 

AddCssClass will add the class name concatenated above it.

+25
source share

I need other attributes that need to be combined (except for the class), so AddCssClass () was not enough. I wrote an extension method to do what I thought MergeAttributes should have done:

 public static class TagBuilderExtensions { public static void TrueMergeAttributes(this TagBuilder tagBuilder, IDictionary<string, object> attributes) { foreach (var attribute in attributes) { string currentValue; string newValue = attribute.Value.ToString(); if (tagBuilder.Attributes.TryGetValue(attribute.Key, out currentValue)) { newValue = currentValue + " " + newValue; } tagBuilder.Attributes[attribute.Key] = newValue; } } } 
+4
source share

All Articles