Html Encoding Nuggets With ASP.NET MVC 2

asp.net, code, asp.net mvc comments edit

This is the second in a three part series related to HTML encoding blocks, aka the <%: ... %> syntax.

In a recent blog post, I introduced ASP.NET 4’s new HTML Encoding code block syntax as well as the corresponding IHtmlString interface and HtmlString class. I also mentioned that ASP.NET MVC 2 would support this new syntax when running on ASP.NET 4.

In fact, you can try it out now by downloading and installing Visual Studio 2010 Beta 2.

I’ve also mentioned in the past that we are not conditionally compiling ASP.NET MVC 2 for each platform. Instead, we’re building System.Web.Mvc.dll against ASP.NET 3.5 SP1 and simply including that one in VS08 and VS10. Thus when you’re running ASP.NET MVC 2 on ASP.NET 4, it’s the same byte for byte assembly as the same one you would run on ASP.NET 3.5 SP1.

This fact ought to raise a question in your mind. If ASP.NET MVC 2 is built against ASP.NET 3.5 SP1, how the heck does it take advantage of the new HTML encoding blocks which require that you implement an interface introduced in ASP.NET 4?

The answer involves a tiny bit of voodoo black magic we’re doing in ASP.NET MVC 2.voodoo

We introduced a new type MvcHtmlString which is created via a factory method, MvcHtmlString.Create. When this method determines that it is being called from an ASP.NET 4 application, it uses Reflection.Emit to dynamically generate a derived type which implements IHtmlString.

If you look at the source code for ASP.NET MVC 2 Preview 2, you’ll see the following method call when we are instantiating an MvcHtmlString:

Type dynamicType = DynamicTypeGenerator.
  GenerateType("DynamicMvcHtmlString", 
    typeof(MvcHtmlString), new Type[] {

Note that we’re using a new internal class, DynamicTypeGenerator, to generate a brand new type named DynamicMvcHtmlString. This type derives from MvcHtmlString and implements IHtmlString. We’ll return this instance instead of a standard MvcHtmlString when running on ASP.NET 4.

When running on ASP.NET 3.5 SP1, we simply new up an MvcHtmlString and return that, completely bypassing the Reflection.Emit logic. Note that we only generate this type once per AppDomain so you only pay the Reflection Emit cost once.

The code in DynamicTypeGenerater is standard Reflection.Emit stuff which at runtime creates an assembly at runtime, adds this new type to it, and returns a lambda used to instantiate the new type. If you’ve never seen Reflection.Emit code, it’s worth a look.

In general, we really frown on this sort of “tricky” code as it’s often hard to maintain and a potential bug magnet. For example, since System.Web.Mvc.dll is security transparent, we needed to make sure that the assembly we generate is marked with the SecurityTransparentAttribute. This is something that would be easy to overlook until you start testing in medium trust scenarios.

However, in this case, the type we’re generating is very small and very simple. Not only that, we only need to keep this code for one version of ASP.NET MVC. ASP.NET MVC 3 will be compiled against ASP.NET 4 only (no support for ASP.NET 3.5 planned) and we’ll be able to remove this “clever” code and have much more straightforward code. I’m looking forward to that. :)

In any case, the point of this post was to fulfill a promise I made in an earlier post where I said I’d give some more details on how ASP.NET MVC 2 works with the new Html encoding block feature.

This is all behind-the-scenes detail that’s not necessary to understand to use ASP.NET MVC, but might be interesting to some of you. Especially those who ever find themselves in a situation where you need to support forward compatibility.

Comments