What Is an MVChtmlstring and When Should I Use It

What is an MvcHtmlString and when should I use it?

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"]) %>.

HtmlString vs. MvcHtmlString

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.

If you're ever going to drop back to MVC 2 it might make sense to use IHtmlString or var for values returned from MVC functions. Alternatively I think you can now just switch to HtmlString throughout.

MvcHtmlString and HtmlString seem pretty useless wrappers around a simple string?

Their main purpose is to implement the IHtmlString marker interface which was introduced in ASP.NET 4.0.

This is part of the Auto-Encoding feature of ASP.NET 4.0+. Before ASP.NET 4.0 we had only this syntax available:

<%= … %>

And this was simply injecting the string into the generated HTML. In 4.0 following syntax has been added:

<%: … %>

Which is a syntax we all should be using now. The difference with old syntax is that the string will be HTML encoded by the framework.

But there are some cases when we don't want to encode the string as it is already a properly encoded HTML (for example it is an output from HtmlHelper). In such cases we should return a class which implements IHtmlString. The new syntax will be happy to accept this instead of string and will not try to encode this, it will just output the string returned by .ToHtmlString() method of the interface. This way we don't have two think if we should use old syntax or new syntax.

Now one can ask why there is a HtmlString and MvcHtmlString class. The answer is Razor. The Razor syntax:

@...

is also encoding everything by default. Now the Razor was introduced in ASP.NET MVC 2.0 which was able to work on .Net Framework 3.5 and there was no IHtmlString or HtmlString there - MvcHtmlString was the marker class for Razor, now it is kept only for backward compatibility.

Difference between MvcHtmlString.Create() and Html.Raw()

This is an excellent opportunity to look at the source code that's available to us for ASP.NET (https://github.com/aspnet/AspNetWebStack/).

Looking at HtmlHelper.cs, this is the code for Html.Raw():

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

public IHtmlString Raw(object value)
{
return new HtmlString(value == null ? null : value.ToString());
}

And this is the code for the MvcHtmlString class:

namespace System.Web.Mvc
{
public sealed class MvcHtmlString : HtmlString
{
[SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "MvcHtmlString is immutable")]
public static readonly MvcHtmlString Empty = Create(String.Empty);

private readonly string _value;

public MvcHtmlString(string value)
: base(value ?? String.Empty)
{
_value = value ?? String.Empty;
}

public static MvcHtmlString Create(string value)
{
return new MvcHtmlString(value);
}

public static bool IsNullOrEmpty(MvcHtmlString value)
{
return (value == null || value._value.Length == 0);
}
}
}

The most significant difference is that Html.Raw() accepts any object, while MvcHtmlString.Create() only accepts strings.
Also, Html.Raw() returns an interface, while the Create method returns an MvcHtmlString object.
Lastly, the Create deals with null differently.

MvcHtmlString.Create() vs new MvcHtmlString()

Here's the actual code according to the JetBrains (R#) decompiler:

public static MvcHtmlString Create(string value)
{
return new MvcHtmlString(value);
}

So, I think you can be pretty certain there's no difference. I have been consistently using Create thinking there might one day be other static factory methods, and it would be more consistent to always use them, but so far, that hasn't happened.

MvcHtmlString with Razor statements included

Your helper needs to use the inbuilt helper methods for generating your html. For example

MvcHtmlString label = LabelExtensions.LabelFor(helper, expression});

Refer this example for creating a helper that outputs similar html including the label, textbox and validation message.

Comparing 2 variables typed MvcHtmlString is always false

public String GetBrowserName()
{
ViewBag.logged = false;
return (Request.Browser.Browser.ToLowerInvariant());
}

So, the Html.Action returns an MvcHtmlString (i don't know why) but is possible to force it to be a string directly in the cshtml page :

@if (ViewBag.BrowserName == null)
{
ViewBag.BrowserName = Html.Action("GetBrowserName", "Services").ToString();
}

now compare the 2 string :

if (ViewBag.BrowserName == "safari")

Html.ActionLink and MvcHtmlString

if i understood correctly you want to write html attribute to a element so u can declare it on html.actionlink html attributes as you can see on the code ( if you want to add class attribute you need write with @symbol like : new { style = "font-size:smaller", @class = "xClass"}

<ul class="vlistmenu">
@foreach (var m in Model)
{
var link = m.LinkName + "<br /><a style=\"font-size:smaller\">By: Ronron (July 11, 2011)</a>");
<li class="forum">@Html.ActionLink(link, "Details", "Forum", new { id = m.Id }, new { style = "font-size:smaller"})</li>
}

Addition for your comment, you can write a custom helper

Raw ActionLink linkText

or you can make manual a tag via url.action method so it will give links according to your controller action but tags implemented manually

<a href="@Url.Action("Details","Forum",new { id = m.Id })">@m.linkname<br /><span style="font-size:smaller">By: Ronron (July 11, 2011)</span></a>

MvcHtmlString.Create() method does not return Html encoded string

I agree that the documentation seems misleading for MvcHtmlString.

However, MvcHtmlString is intended to be used when you don't want a string to be HTML encoded. The default behaviour of razor is to encode the output.

The Html string that you pass to it should already be encoded to ensure that it is outputted without additional encoding.

So assuming the following HTML helper:

public static class HtmlHelper
{
public static string GetHtmlString(this System.Web.Mvc.HtmlHelper htmlHelper)
{
return "<h1>myHeading</h1>";
}

public static MvcHtmlString GetMvcHtmlString(this System.Web.Mvc.HtmlHelper htmlHelper)
{
return MvcHtmlString.Create("<h1>myHeading</h1>");
}
}

With the Razor view:

@Html.GetHtmlString()
@Html.GetMvcHtmlString()

The output would be:

<h1>myHeading</h1>

myHeading



Related Topics



Leave a reply



Submit