How to concatenate several MvcHtmlString instances
Asked Answered
T

4

69

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).

Twig answered 11/8, 2010 at 16:49 Comment(0)
H
28

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 "&lt;tag&gt;"
<%: hs %> -- outputs "<tag>"
Histochemistry answered 11/8, 2010 at 18:22 Comment(0)
M
60

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

Mainsail answered 12/8, 2010 at 3:52 Comment(3)
This doesn't compile for me, I've changed it: public static MvcHtmlString Concat(this MvcHtmlString first, params MvcHtmlString[] strings) { return MvcHtmlString.Create(first.ToString() + string.Concat(strings.Select(s => s.ToString()).ToArray())); }Swiss
is there a reason the input params aren't IHtmlString?Foeticide
IHtmlString didn't exist in .NET 3.5Mainsail
H
28

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 "&lt;tag&gt;"
<%: hs %> -- outputs "<tag>"
Histochemistry answered 11/8, 2010 at 18:22 Comment(0)
G
21

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.

Gorman answered 5/12, 2010 at 17:6 Comment(0)
L
4

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
    )
);
Loats answered 5/1, 2018 at 21:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.