Click here to Skip to main content
15,945,939 members
Articles / Web Development / CSS

Support for Generics in ASP.NET Server Controls

Rate me:
Please Sign up or sign in to vote.
4.77/5 (16 votes)
29 Jan 2009CPOL4 min read 61.6K   446   29   13
Implementation of a framework to support Generics in ASP.NET server controls, including strong-typing of ITemplate containers.

Generics in ASP .NET? Why?

Anyone who has ever built a WebForms based application has no doubt come across the well-worn Repeater control. A staple of web programming, it allows for the display of a collection of items, and exposes the items through the Eval or Bind methods.

Under the hood, Eval and Bind work through Reflection in order to provide late binding support. This is also what you see if you reference properties such as:

<%# Container.DataItem.PropertyNameHere %>

The reason for this is that ASP.NET allows transparent late binding, so even though it believes that Container.DataItem is typed as 'Object', the evaluation will only occur at runtime. This leads to all sorts of problems such as:

  • Pages breaking when a property is changed, and no warnings at compile-time.
  • Reduced performance, as every data-field display point becomes a Reflection call.

If we could tell ASP.NET what the type of the data items actually are, though, then during site start-up/compilation, we would be able to ensure the right types are being used, and no late-binding ever occurs. Compile time checking of all pages, master-pages, and user control binding tags sounds good?

If that's not enough for you, what about full intellisense support?


Generics in ASP.NET? How?

During start-up and the first hit to a page in a given folder, ASP.NET performs batch compilation of your ASPX files. That is, the conversion of them and the content therein into actual .NET code that will be run. The trouble previously with ASP.NET Generics was that there is no syntax support in ASP.NET to specify a generic type, for example:

<asp:Repeater ID="Repeater1" runat="Server" />

is all well and good, but you can't say:

<asp:GenericRepeater<String> ID="StringRepeater" />

As a result, we're going to have to find a workaround. I've ended up taking a very similar route to another tutorial that gives a typed Repeater implementation, by Andrey Shchekin. You can find his tutorial here. The way this works is as follows:

  • We intercept compile-time construction of pages using a ControlBuilder sub-class assigned to a non-generic class.
  • This ControlBuilder's Init method switches the non-generic type for a real generic type, using type-names read from properties of the non-generic control.
  • We wrap the real type inside a TypeDelegator that intercepts any calls to properties of the type (such as the templated containers).
  • Whenever ASP.NET requests the TemplateContainer attribute of the type, we give it back a dynamically constructed instance that contains the correct strong-typing information.

In the example code, I've created a 'GenericRepeater' that displays a strongly typed collection and the items therein. I have then sub-classed that GenericRepeater with <Object, Object> in order to create an ObjectRepeater like so:

[GenericControlType(typeof(GenericRepeater<,>), "CollectionTypeName", "ItemTypeName")]
public class ObjectRepeater : GenericRepeater<IEnumerable<Object>, Object>

The ObjectRepeater inherits the real generic repeater type, and the attributes tell ASP.NET to use the special control builder instead of the base one. The GenericTemplatedControlBuilder then looks for the GenericControlType attribute, and will activate the 'real' GenericRepeater instance with the two type parameters.

Inside the generic repeater implementation, we mark up the various ITemplate properties with other attributes:

[^__strong__^GenericTemplateContainerParameter(typeof(IndexedDataContainer<,>), 0, 1)]
public ITemplate ItemTemplate { get; set; }

The GenericTemplateContainerParameter declaration tells the system what type of data container to instantiate, and also the indices of the generic parameters to pass down. Thus, since IndexedDataContainer takes two generic parameters, we are telling to take generic parameters 0 (TCollectionType) and 1 (TItemType) from the GenericRepeater as the relevant parameters.

When ASP.NET scans the properties of the control, we have now switched the control for a generic control and instructed our GenericControlPropertyDelegator to remap all calls for TemplateContainer to our real, generic template containers.

The Final Product

Now that we have everything in play, let's define a simple ASP.NET page that uses the control:


And, there you have it, a simple generics framework for ASP.NET that allows you to deal with pretty much any generic control scenario, and is not specifically tied down to the example for use with Repeaters.

Notes About the Code

The example code supplied does not actually implement any post-back support, so don't be surprised if you need to add some code to load/save data in the viewstate and so forth.

Additionally, if you're going to reference this code on your own Web Applications, please ensure you take the web.config elements across to register the CFC tag prefix.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Written By
Software Developer (Senior) Insurance Industry
United Kingdom United Kingdom
Steve Gray is a Senior Developer at a British insurance company, working on a popular aggregator. When he's not writing ASP .NET, it's because there's SQL or WCF to write instead.

Comments and Discussions

GeneralNot working on 4 Pin
Hedgic24-Jan-11 4:27
Hedgic24-Jan-11 4:27 
GeneralRe: Not working on 4 Pin
Steven James Gray1-Feb-11 21:19
Steven James Gray1-Feb-11 21:19 
GeneralFantastic Pin
BKK199223-Sep-09 9:40
BKK199223-Sep-09 9:40 
QuestionAny Attribute to Hide Generic Class in ASPX? Pin
Barry Dorman23-Apr-09 10:02
Barry Dorman23-Apr-09 10:02 
AnswerRe: Any Attribute to Hide Generic Class in ASPX? Pin
Steven James Gray11-Oct-09 18:15
Steven James Gray11-Oct-09 18:15 
One mechanism that would achieve this is changing the accessibility of the generic version. However this would then cause the ASPX compilation to break since the dynamic injection occurs prior to this. If you're that bothered you can always put the generic implementations in a seperate namespace and then not bother to add the tagprefixes to web.config for that namespace.
GeneralGreat code - but some queries... Pin
MR_SAM_PIPER2-Feb-09 21:05
MR_SAM_PIPER2-Feb-09 21:05 
GeneralRe: Great code - but some queries... Pin
Steven James Gray3-Feb-09 0:37
Steven James Gray3-Feb-09 0:37 
GeneralGreat job! Pin
Andrey Shchekin1-Feb-09 10:44
Andrey Shchekin1-Feb-09 10:44 
Questionwhat abound Bind ? Pin
emperon30-Jan-09 8:49
emperon30-Jan-09 8:49 
AnswerRe: what abound Bind ? [modified] Pin
Steven James Gray30-Jan-09 19:01
Steven James Gray30-Jan-09 19:01 
GeneralMy vote of 2 Pin
ProJester130-Jan-09 2:43
ProJester130-Jan-09 2:43 
QuestionListView? Pin
bertkid29-Jan-09 8:00
bertkid29-Jan-09 8:00 
AnswerRe: ListView? Pin
Steven James Gray29-Jan-09 8:44
Steven James Gray29-Jan-09 8:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.