In my MVC application, I have a helper class designed to render a group of related buttons. I'm trying to pass in the buttons' HTML attributes as an anonymous object:
new { @class="myClass1 myClass2" }
The helper emits HTML as an MvcHtmlString
, which I'm currently building like this:
foreach (var b in _buttons)
{
sb.AppendFormat("<button type='submit' name='{0}' {1}>{2}</button>",
b.Value,
b.HtmlAttributes,
b.Text);
}
My problem is that the above code produces invalid HTML:
<button type='submit' name='Foo' { class = myClass1 myClass2 }>Bar</button>
Unfortunately, since it's passed to the helper as an object
, I don't have type information to work with. I could ToString
the object and parse the result, but that seems pretty silly. How can I programmatically convert an anonymous object into key="value"
style HTML attributes? Is there an existing utility for this?
You should use the TagBuilder
class, which builds HTML tags for you.
You can then write
builder.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(HtmlAttributes));
As it turns out, there's a static method for this on the HtmlHelper
class:
HtmlHelper.AnonymousObjectToHtmlAttributes(b.HtmlAttributes)
This solved my issue:
foreach (var b in _buttons)
{
var dict = HtmlHelper.AnonymousObjectToHtmlAttributes(b.HtmlAttributes);
var attr = dict.Keys.Zip(
dict.Values,
(k, v) => string.Format("{0}='{1}'", k, v));
sb.AppendFormat("<button type='submit' name='{0}' {1}>{2}</button>",
b.Value,
string.Join(" ", attr),
b.Text);
}
I also tried it with a TagBuilder and got about the same amount of code.
Edit: As Slaks pointed out, doing it this way is a potential XSS vulnerability. There was no risk in my specific use case, but TagBuilder seems like the best practice.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With