MVC: Strongly Typed ViewData Without A Code-Behind
07 Jan 2008If 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] ]
- "ParentType" is fairly obvious. This is the generic object that you want to create a reference to.
- "`1[ [" is a bit more obscure. The "`1" specifies the number of generics in this argument, which we'll come back to in a second. The double square brackets are required. A single square bracket will NOT work.
- "ChildType" is the type of object you wish to have the generic consume (what is the proper terminology here? anyone know?).
- "ChildTypeAssembly" is the name of the assembly (NOT the namespace) that contains the ChildType. All of your common value types will be located in "mscorlib".
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]]