Shaun Xu

The Sheep-Pen of the Shaun



Shaun, the author of this blog is a semi-geek, clumsy developer, passionate speaker and incapable architect with about 10 years’ experience in .NET. He hopes to prove that software development is art rather than manufacturing. He's into cloud computing platform and technologies (Windows Azure, Aliyun) as well as WCF and ASP.NET MVC. But right now, Shaun is being attracted by JavaScript (Angular.js and Node.js) and he likes it.

Shaun is working at IGT Technology Development (Beijing) Co., Ltd. as the architect and product manager responsible for design and develop the next generation, web-based casino management system.


One of my colleague and friend, Robin is playing and struggling with the ASP.NET MVC 2 on a project these days while I’m struggling with a annoying client. Since it’s his first time to use ASP.NET MVC he was meetings with a lot of problem and I was very happy to share my experience to him. Yesterday he asked me when he attempted to insert a <br /> element into his page he found that the page was rendered like this which is bad.


He found his <br /> was shown as a part of the string rather than creating a new line. After checked a bit in his code I found that it’s because he utilized a new ASP.NET markup supported in .NET 4.0 – “<%: %>”.


If you have been using ASP.NET MVC 1 or in .NET 3.5 world it would be very common that using <%= %> to show something on the page from the backend code. But when you do it you must ensure that the string that are going to be displayed should be Html-safe, which means all the Html markups must be encoded. Otherwise this might cause an XSS (cross-site scripting) problem. So that you’d better use the code like this below to display anything on the page.

image In .NET 4.0 Microsoft introduced a new markup to solve this problem which is <%: %>. It will encode the content automatically so that you will no need to check and verify your code manually for the XSS issue mentioned below. But this also means that it will encode all things, include the Html element you want to be rendered. So I changed his code like this and it worked well.


After helped him solved this problem and finished a spreadsheet for my boring project I considered a bit more on the <%: %>. Since it will encode all thing why it renders correctly when we use “<%: Html.TextBox(“name”) %>” to show a text box? As you know the Html.TextBox will render a “<input name="name" id="name" type="text"/>” element on the page. If <%: %> will encode everything it should not display a text box. So I dig into the source code of the MVC and found some comments in the class MvcHtmlString.

   1: // In ASP.NET 4, a new syntax <%: %> is being introduced in WebForms pages, where <%: expression %> is equivalent to
   2: // <%= HttpUtility.HtmlEncode(expression) %>. The intent of this is to reduce common causes of XSS vulnerabilities
   3: // in WebForms pages (WebForms views in the case of MVC). This involves the addition of an interface
   4: // System.Web.IHtmlString and a static method overload System.Web.HttpUtility::HtmlEncode(object).  The interface
   5: // definition is roughly:
   6: //   public interface IHtmlString {
   7: //     string ToHtmlString();
   8: //   }
   9: // And the HtmlEncode(object) logic is roughly:
  10: //   - If the input argument is an IHtmlString, return argument.ToHtmlString(),
  11: //   - Otherwise, return HtmlEncode(Convert.ToString(argument)).
  12: //
  13: // Unfortunately this has the effect that calling <%: Html.SomeHelper() %> in an MVC application running on .NET 4
  14: // will end up encoding output that is already HTML-safe. As a result, we're changing out HTML helpers to return
  15: // MvcHtmlString where appropriate. <%= Html.SomeHelper() %> will continue to work in both .NET 3.5 and .NET 4, but
  16: // changing the return types to MvcHtmlString has the added benefit that <%: Html.SomeHelper() %> will also work
  17: // properly in .NET 4 rather than resulting in a double-encoded output. MVC developers in .NET 4 will then be able
  18: // to use the <%: %> syntax almost everywhere instead of having to remember where to use <%= %> and where to use
  19: // <%: %>. This should help developers craft more secure web applications by default.
  20: //
  21: // To create an MvcHtmlString, use the static Create() method instead of calling the protected constructor.

The comment said the encoding rule of the <%: %> would be:

  • If the type of the content is IHtmlString it will NOT encode since the IHtmlString indicates that it’s Html-safe.
  • Otherwise it will use HtmlEncode to encode the content.

If we check the return type of the Html.TextBox method we will find that it’s MvcHtmlString, which was implemented the IHtmlString interface dynamically.

image That is the reason why the “<input name="name" id="name" type="text"/>” was not encoded by <%: %>. So if we want to tell ASP.NET MVC, or I should say the ASP.NET runtime that the content is Html-safe and no need, or should not be encoded we can convert the content into IHtmlString. So another resolution would be like this.

image Also we can create an extension method as well for better developing experience.

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Web;
   5: using System.Web.Mvc;
   7: namespace ShaunXu.Blogs.IHtmlStringIssue
   8: {
   9:     public static class Helpers
  10:     {
  11:         public static MvcHtmlString IsHtmlSafe(this string content)
  12:         {
  13:             return MvcHtmlString.Create(content);
  14:         }
  15:     }
  16: }

Then the view would be like this.

image And the page rendered correctly.







In this post I explained a bit about the new markup in .NET 4.0 – <%: %> and its usage. I also explained a bit about how to control the page content, whether it should be encoded or not. We can see the ASP.NET MVC gives us more points to control the web pages.


Hope this helps,


All documents and related graphics, codes are provided "AS IS" without warranty of any kind.
Copyright © Shaun Ziyan Xu. This work is licensed under the Creative Commons License.




Gravatar # re: <%: %>, HtmlEncode, IHtmlString and MvcHtmlString
Posted by Martin on 6/21/2010 4:18 PM
Hello, thanks for the article.
The only suggestion is to name the extension method more concisely. "IsHtmlSafe" implies boolean return value. What do you think about "ToHtmlSafe" instead?
Gravatar # re: <%: %>, HtmlEncode, IHtmlString and MvcHtmlString
Posted by Shaun on 6/26/2010 4:47 PM
That's correct thanks for your advise, Martin.
Gravatar # re: <%: %>, HtmlEncode, IHtmlString and MvcHtmlString
Posted by Bergfall on 9/14/2010 8:50 PM
Great article, thanks!
Gravatar # re: <%: %>, HtmlEncode, IHtmlString and MvcHtmlString
Posted by Ali on 7/6/2012 3:25 AM
Now I know what is going on. Your explanation was very helpful.
Post A Comment