232

The documentation for MvcHtmlString is not terribly enlightening:

Represents an HTML-encoded string that should not be encoded again.

It's not clear to me what exactly the implications of this are. It seems that some HTML helper methods return an MvcHtmlString, but several examples I've seen online of custom helpers just return a regular string.

Questions:

What is an MvcHtmlString?

When should I choose MvcHtmlString over string and vice versa? Why?

1
  • I vote for link of document :D it's good for me. Thank you! Commented Nov 5, 2020 at 3:54

4 Answers 4

249

ASP.NET 4 introduces a new code nugget syntax <%: %>. Essentially, <%: foo %> translates to <%= HttpUtility.HtmlEncode(foo) %>. The team is trying to get developers to use <%: %> instead of <%= %> wherever possible to prevent XSS.

However, this introduces the problem that if a code nugget already encodes its result, the <%: %> syntax will re-encode it. This is solved by the introduction of the IHtmlString interface (new in .NET 4). If the foo() in <%: foo() %> returns an IHtmlString, the <%: %> syntax will not re-encode it.

MVC 2's helpers return MvcHtmlString, which on ASP.NET 4 implements the interface IHtmlString. Therefore when developers use <%: Html.*() %> in ASP.NET 4, the result won't be double-encoded.

Edit:

An immediate benefit of this new syntax is that your views are a little cleaner. For example, you can write <%: ViewData["anything"] %> instead of <%= Html.Encode(ViewData["anything"]) %>.

5
  • I'd add that MVC 2 is compiled against .Net 3.5, not 4. This means that MvcHtmlString doesn't implement IHtmlString because that only exists in 4. The <%: syntax must duck-type - it will always call .ToHtmlString() before .ToString() regardless of interface.
    – Keith
    Commented Jul 8, 2010 at 7:49
  • 2
    I stand corrected - actually the MvcHtmlString.Create method detects whether IHtmlString is available and dynamically creates the returned class to support it if it is: windowsitpro.com/article/net-framework/Encoding-and-Strings/…
    – Keith
    Commented Jul 8, 2010 at 8:50
  • Follow Up: Is there a meaningful difference between MvcHtmlString and HtmlString? After reading the docs linked above, I still did not know what MvcHtmlString gives me that HtmlString does not.
    – flipdoubt
    Commented Jan 9, 2013 at 13:41
  • @flipdoubt - There is no meaningful difference.
    – Levi
    Commented Jan 10, 2013 at 6:34
  • 2
    There is one very slight difference between the two. MvcHtmlString will return String.Empty in ToString() or ToHtmlString() if you pass it a null string. HtmlString will continue to return null, though.
    – rossisdead
    Commented Mar 6, 2013 at 16:59
93

This is a late answer but if anyone reading this question is using razor, what you should remember is that razor encodes everything by default, but by using MvcHtmlString in your html helpers you can tell razor that it doesn't need to encode it.

If you want razor to not encode a string use

@Html.Raw("<span>hi</span>")

Decompiling Raw(), shows us that it's wrapping the string in a HtmlString

public IHtmlString Raw(string value) {
    return new HtmlString(value); 
}

"HtmlString only exists in ASP.NET 4.

MvcHtmlString was a compatibility shim added to MVC 2 to support both .NET 3.5 and .NET 4. Now that MVC 3 is .NET 4 only, it's a fairly trivial subclass of HtmlString presumably for MVC 2->3 for source compatibility." source

11

A nice practical use of this is if you want to make your own HtmlHelper extensions. For example, I hate trying to remember the <link> tag syntax, so I've created my own extension method to make a <link> tag:

<Extension()> _
Public Function CssBlock(ByVal html As HtmlHelper, ByVal src As String, ByVal Optional ByVal htmlAttributes As Object = Nothing) As MvcHtmlString
    Dim tag = New TagBuilder("link")
    tag.MergeAttribute("type", "text/css")
    tag.MergeAttribute("rel", "stylesheet")
    tag.MergeAttribute("href", src)
    tag.MergeAttributes(New RouteValueDictionary(htmlAttributes))
    Dim result = tag.ToString(TagRenderMode.Normal)
    Return MvcHtmlString.Create(result)
End Function

I could have returned String from this method, but if I had the following would break:

<%: Html.CssBlock(Url.Content("~/sytles/mysite.css")) %>

With MvcHtmlString, using either <%: ... %> or <%= ... %> will both work correctly.

9

You would use an MvcHtmlString if you want to pass raw HTML to an MVC helper method and you don't want the helper method to encode the HTML.

5
  • Hmm...I thought the whole point of an HTML helper method was to encode HTML. What would I do otherwise with an HTML helper method?
    – devuxer
    Commented Feb 19, 2010 at 0:47
  • And, besides that, when would I want to return an MvcHtmlString from an HTML helper method?
    – devuxer
    Commented Feb 19, 2010 at 0:49
  • Pass to or return from. You would want to return one if your HTML helper generates pre-escaped HTML and you don't want anyone else re-escaping it.
    – SLaks
    Commented Feb 19, 2010 at 0:51
  • 1
    Okay, I think that gets me a little bit closer, but (at the risk of coming across as a smart ass) how do I decide whether I want anyone else re-escaping it? Is it generally good/bad practice to give someone the ability to mess with escaped html? I've never seen a construct like this before. "It's like a string, but please don't touch it...not that there's anything preventing you from touching it, but we'd prefer you don't." What is that about?
    – devuxer
    Commented Feb 19, 2010 at 1:15
  • 1
    The point is that unlike a regular string, this string has already been encoded. Therefore, there's no need to touch it.
    – SLaks
    Commented Feb 19, 2010 at 14:02

Not the answer you're looking for? Browse other questions tagged or ask your own question.