Marc Cals
Marc Cals

Reputation: 2989

@Helper razor enconding html

According to https://blog.cindypotvin.com/character-encodings-with-razor-helpers/ and some other resources @Helper blocks return a HelperResult class that Implements IHtmlString.

Being and HtmlString all the string inside the @helper blocks should not be encoded. But I have the following scenario (the real scenario is more complex) where the html is encoded

@helper Test(){
   @(new HtmlString("<label>Test 1</label>"))
   @(new HtmlString("<label>Test 2</label>"))
}

When I check the view in browser I see literally <label> Test 1 .... because the Html code generate inside the @helper Test is between quotes.

But adding a RawString then it works correctly.

@helper Test(){
    @(new RawString(new HtmlString("<label>Test 1</label>").ToString()))
    @(new RawString(new HtmlString("<label>Test 2</label>").ToString()))
}

Taking into account that HtmlString it´s for Razor to not encode a string and @Helper returns HtmlString, I don´t get why I need to add RawString to render correctly the html code on browser.

Upvotes: 0

Views: 225

Answers (1)

Peter B
Peter B

Reputation: 24136

This looks like a matter of incorrect expectations and/or interpretations...

A @helper method renders its output to an output stream, resulting in a plain text string. That string may contain HTML, and if so, then that HTML may or may not have been HTML encoded along the way (depending on how the helper was written). The resulting plain text string is then returned inside an IHtmlString wrapper object.

If an IHtmlString object is rendered using @(...), to Razor this means 'don't HTML-encode this, that was done already if/when/where needed'.

In short, doing @Test() sends the exact string content without further encoding to the browser (which then interprets it). If your aim was to encode it, then you could use @(Test().ToString()) because that pulls the string out of its IHtmlString protective cover, and then it will be HTML-Encoded.

If you inspect Test().ToString() then you can see the plain-text content, which for your Test() will look like "<label>...</label><label>...</label>". There's not a trace of the original HtmlString objects that you used, they were all rendered, and nothing was HTML-Encoded because you used @(new HtmlString(...)) for each.

It may be worth noting that these three @helper methods all have exactly the same output (except perhaps for some whitespace):

@helper Test()
{
   <label>Test</label>
}

@helper Test()
{
   @(new HtmlString("<label>Test</label>"))
}

@helper Test()
{
   @(Html.Raw("<label>Test</label>"))
}

The result for all of these is the plain string "<label>Test</label>" wrapped as an IHtmlString.

Finally, if you would WANT the <label> to be HTML-Encoded, then this is what you'd need to use:

@helper Test()
{
   @("<label>Test</label>")
}

The result of this is the plain string "&lt;label&gt;Test&lt;/label&gt;" wrapped as an IHtmlString.

Upvotes: 2

Related Questions