How to concatenate several MvcHtmlString instances
asp.net Mvc-2Html HelperMvchtmlstringasp.net Mvc-2 Problem Overview
I have some doubts about how to concatenate MvcHtmlString instances because of this information found in MSDN :
> MvcHtmlString Class Represents an HTML-encoded string that > should not be encoded again
Do I risk that strings are HTML-encoded twice when using code like this:
var label = Html.LabelFor(model => model.Email);
var textbox = Html.TextBoxFor(model => model.Email);
var validation = Html.ValidationMessageFor(model => model.Email);
var result = MvcHtmlString.Create(
label.ToString() + textbox.ToString() + validation.ToString());
(note: this is supposed to go into an HtmlHelper extension method to reduce code-duplication in views).
asp.net Mvc-2 Solutions
Solution 1 - asp.net Mvc-2
Too bad C# won't let us override the + operator here! How about using an extension method instead?
public static MvcHtmlString Concat(this MvcHtmlString first, params MvcHtmlString[] strings)
{
return MvcHtmlString.Create(first.ToString() + string.Concat(strings.Select(s => s.ToString())));
}
This could probably be optimized, but you can run with it. It should be fairly trivial to prove that this doesn't double encode strings with a unit test.
Usage sample:
label.Concat(textbox, validation)
And now a shameless plug for my blog: Use TagBuilder or HtmlTags to clean up your HTML
Solution 2 - asp.net Mvc-2
Your code is correct.
That snippet from MSDN means that an encoding View Engine (such as the Aspx view engine in .NET 4 when using <%: %>
or the Razor view engine in MVC 3) should not re-encode the string value of the object.
So for example:
string s = "<tag>";
var hs = MvcHtmlString.Create(s);
<%: s %> -- outputs "<tag>"
<%: hs %> -- outputs "<tag>"
Solution 3 - asp.net Mvc-2
I went for this approach:
private static MvcHtmlString Concat(params MvcHtmlString[] items)
{
var sb = new StringBuilder();
foreach (var item in items.Where(i => i != null))
sb.Append(item.ToHtmlString());
return MvcHtmlString.Create(sb.ToString());
}
It's just a utility method that I use inside the classes with extension methods for HtmlHelper.
Solution 4 - asp.net Mvc-2
I know this is super old, but yet another way (which I find to be more elegant), is to use an overload of the String method Concat, which metadata definition is
public static String Concat(params object[] args);
that basically ToStrings each one of the objects passed in and then concatenates the results and returns the concatenated string.
So the final result would be:
var result = MvcHtmlString.Create(
string.Concat(
label, textbox, validation
)
);