Troy Goode


MVC: Strongly Typed ViewData Without A Code-Behind

If you've tried to use strongly-typed ViewData with a ViewPage or ViewContentPage without using a code-behind file you may have run into the curious scenario of how to specify a generic in the <%@ Page %> element's Inherits attribute.

The Problem

Let's say you wanted to specify that the ViewData for this view would be an integer. Normally you would specify this in the code-behind like so:

Since we don't have a code-behind file though, we have to change the .aspx file's <%@ Page %> element. Trying to set it to the following will not work:

The Basic Answer

The value of the Inherits attribute appears to be delivered straight to the CLR without any language specific parsing, which means we have to specify it the way the CLR wants to interpret it. I browsed around and found (here and here) some information that points out the proper way to do this:

WTF?

Eww, huh? The syntax is gnarly, but it gets the job done. Let's break the syntax down to make sure you understand what is going on:

ParentType`1[ [ChildType,ChildTypeAssembly] ]

Multiple Generic Types

Let's say ViewPage took two arguments as part of its generic declaration area (ie: ViewPage<X,Y>). It doesn't, by the way, but we'll pretend it does for the sake of argument; you may find this information useful someday.

To have two type parameters, you'll have to change the "`1" to a "`2" and add an extra "[ChildType, ChildTypeAssembly]" reference, separated by a space. More parameters would continue to follow the same logic.

If you wanted to achieve the equivalent of ViewPage<int,string> it would look like this:

System.Web.Mvc.ViewPage`2[ [System.Int32,mscorlib], [System.String,mscorlib] ]

A Generic of Generics

A more likely scenario is that you may want to have your ViewData be a generic List<T>. In this case you'll just nest the declarations. If you wanted to pass ViewData of the type List<string> to the ViewPage it would look like:

System.Web.Mvc.ViewPage`1[[System.Collections.Generic.List`1[[System.String,mscorlib]], mscorlib]]