Tales from the Evil Empire

Bertrand Le Roy's blog


Bertrand Le Roy

BoudinFatal's Gamercard

Tales from the Evil Empire - Blogged

Blogs I read

My other stuff


March 2005 - Posts

What's the difference between generic type parameters and parameters of type Type?

In other words, what's the difference between:

public T GetService<T>()


public object GetService(Type service)

The generic type parameter enables strongly-typed scenarios that would otherwise be impossible. But don't forget that the generic type must be resolvable at compile-time (which is the whole point of generics). So you can't do this:

Type t = Type.GetType("SomeTypeName");
object serviceInstance = GetService<t>();

The type parameter is just that, a type parameter, it's not some parameter of type Type. So for these cases (those where the type you want to instantiate is defined in config, for example), you need the weakly-typed factory.

In this precise scenario of a factory, I prefer to keep both versions so that I can use the strongly-typed generic version wherever possible, and the other one otherwise.

ObjectHierarchicalDataSource sample code
Some time ago, I released the source code for my CompositeHierarchicalDataSource that answers the problem that there is no out-of-the-box way to declaratively bind a Menu or TreeView to a database in ASP.NET 2.0: only XML and SiteMap have hierarchical data sources. You could still do it programmatically, but declaratively is so much more fun...
It's also noticeable that while there is a very handy ObjectDataSource control in ASP.NET 2.0, it does not have a hierarchical equivalent. Basically, the idea would be to declaratively bind a hierarchical control to an arbitrary object graph.
Enter the ObjectHierarchicalDataSource, which transfers many of the nice ideas in ObjectDataSource to the hierarchical realm.
Here's how you can use it:

<my:ObjectHierarchicalDataSource runat=server ID=ObjectInstance1 TypeName="Categories">
    <my:SelectMethod TypeName="CatsCategory" Method="GetCats" />
    <my:SelectMethod TypeName="Cat" PropertyNames="Color,Gender" />

<asp:TreeView Runat=Server ID=categoryTree DataSourceID=ObjectInstance1
ExpandDepth=0 PopulateNodesFromClient=true>
    <asp:TreeNodeBinding TextField="#" ValueField="#" ToolTipField="#" PopulateOnDemand=true />
    <asp:TreeNodeBinding DataMember="CatsCategory" TextField="Name" ValueField="Name"
ToolTipField="Name" PopulateOnDemand=true />
    <asp:TreeNodeBinding DataMember="Cat" TextField="Name" ValueField="Name"
ToolTipField="Description" PopulateOnDemand=true />
    <asp:TreeNodeBinding DataMember="Color" FormatString="Color: {0}" PopulateOnDemand="true"
      SelectAction="None" TextField="Name" ValueField="Name" ToolTipField="#" />
    <asp:TreeNodeBinding DataMember="Gender" PopulateOnDemand="true" SelectAction="None"
      TextField="#" ValueField="#" ToolTipField="#" />

We're giving the data source a type name that will be the root of the graph. This type must have a default parameterless constructor. We don't have to specify a select method on this type because it is enumerable and if you don't specify a select method on an enumerable object, the data source will just assume the enumeration is describing the next level.
CatsCategory, on the other hand, is not directly enumerable, so we must provide the name of a method that will get us the enumeration of objects in the next level: GetCats().
Finally, the third way to describe the children of an object is a list of properties. That's what we're doing for Cat: its children are simply the Color and Gender properties.
Now, all there is to do is to tell the TreeView that will consume the data source (Menu would work in just the same way) how to bind itself to the data. We're using the DataBindings property for that, and for each type (DataMember) that will be present in the object graph, we tell the tree which properties to use for the text, value, tooltip or format string. We also have a default binding for types that we don't want to special-case (such as string).
The "#" bindings express that the "field" we want is not a property but the return value of the ToString() method.
Notice how the tree will populate on demand even with this exotic data source (which could be an absolute must if your data source is infinitely deep).
One of the most interesting parts of the implementation is the way we wrap the objects of the graph in objects that know how to expose their children in the hierarchy in a standardized way but still show all the properties of the wrapped object under Reflection (which the data source of course uses intensively, this is the price of extreme flexibility and ease of declaration). The way it does that is by implementing ICustomTypeDescriptor, which is an amazingly useful interface. Have a look at the ObjectHierarchyData source code if you want more details.
The source code and sample page (which will auto-compile) can be found here:
World safe from mad scientists
After all, we may be safe from the mad scientists at CERN (just kidding: some of these guys are not yet entirely mad) producing low-velocity black holes that could have swallowed the Earth if Hawking radiation just happened not to work after all. Well, the mad scientists at RHIC may have just created black holes (or more correctly objects that act like black holes but may be supersymmetric dual objects to black holes (no, I don't really understand what I'm writing here, just pretending)) and observed them evaporate through Hawking radiation.
If this is confirmed, it means three different things:
  • Black holes have been produced in a laboratory. Scary, but they are very small ones.
  • Hawking radiation works
  • Superstring effects have been observed
An of course, the Earth is safe from destruction by artificial black holes. So we're back to worrying about nuclear holocaust, climate changes, pollution, strangelets, massive epidemies, ateroids hitting the Earth. Ew, that was a close one.
through Julien Ellie.
How do I reduce this ViewState thing?
ViewState is a hugely useful feature of ASP.NET, but it's easy to misuse. It's also a little difficult to apprehend for ASP.NET beginners as it's working behind the scenes. The only thing you see at first is this huge blob on your page source.
If you don't know how ViewState works or what it's for, and even if you do, you should read this MSDN article. In a nutshell, ViewState is a state bag that's maintained from postback to postback. It materializes one of the scopes you can use to maintain state in your application:
  • Context: local to the request (equivalent in scope to a page property).
  • ViewState: local to the page, survives postbacks (but if you open two browsers on the same page, they have separate versions of the ViewState).
  • Session: local to the remote user session (if you open two browsers using CTRL+N, they share the same session, but if you open two completely different instances of the browser, they don't), has a finite lifespan (20 minutes idle time by default), does not survive the browser closing. The Session can be shared across servers in a Web Farm.
  • Cookies: local to the remote user account, can survive the browser closing, has a finite lifespan.
  • Cache: local to the web application, shared by all users, not shared in a farm, expires based on a lifespan or arbitrary dependancies.
  • Application: local to the Web application, shared by all users, not shared in a farm, doesn't expire except if the application is recycled.
  • Static variables: shared by the whole application domain. Don't use that in a web application. Use Application variables instead (unles you really really know what you're doing).
The way it works is by tracking all changes from the moment TrackViewState is called, which happens normally between Init and Load. This means that any change you make after Init will be persisted to ViewState.
So the first thing you can do to reduce the viewstate is to do all initialization work during... yes, Init.
The data that you do want to persist across postbacks must be loaded during... you guessed it, Load.
The way it persists from postback to postback is by serializing all changes since tracking began into the __VIEWSTATE hidden HTML field. This is the big blob you see in your page. To avoid tampering, it is by default MAC-hashed.
There are a few reasons why you could want to completely disable ViewState (which is done by setting EnableViewState to false in the page directive or on any Control):
  1. Your page won't post back: pure contents pages, for example.
  2. Your page will post back, but the data will be completely different for every postback: a search results page where you handle the pagination logic using lazy loading, for example.
  3. Your page will post back, but you chose to rebind the data on every postback.
  4. The control does not handle postback data.
  5. The control does not persist any data.
  6. The control rebinds the data on every postback.
The third and sixth ones are particularly interesting because it's a decision you have to make in the context of your particular application. If the bandwidth the ViewState is eating costs you more than querying the database, then disable ViewState. Otherwise, keep it on but don't bloat it unnecessarily (by moving initialization code to Init and keeping persisted data loading in Load).
If you choose to requery the data on every postback, consider doing it in Init. This way, you can keep the data out of ViewState and still use the ViewState for other properties: you get finer granularity.
Another problem you may hit on ASP.NET 1.1 is that some controls do not like to have their ViewState disabled. DataGrid is one example of a control that more or less ceases to function properly without ViewState. That's why we introduced the concept of ControlState in ASP.NET 2.0. The ControlState is a part of ViewState that can't be disabled. It is used for these very few properties on each control that are absolutely necessary for the control to function. It could be the page number for a pagination control, for example. So in ASP.NET 2.0, you can safely disable ViewState on any of the new controls without them breaking down. GridView, which replaces DataGrid, is one of these controls.
Develop a HttpHandler with full IntelliSense
Ashx files have a bad reputation. There is little documentation about them in v1, and no support for them in Visual Studio 2003. With ASP.NET 2.0 and Visual Studio 2005, this changes, and it becomes as easy to develop an ashx file as any other class.
But what is an ashx file, you may ask? It's an HttpHandler, a class that handles an http request. An ASP.NET page can be considered a kind of elaborate HttpHandler, for example. There are cases where you won't need all the Page infrastructure, WebControls, events and all that. Let's say that you want to stream a thumbnail image to the client, for example. All you need is a reference to the context (to be able to get some information from the QueryString, send data to the response, etc.). That's no more and no less than what the HttpHandler infrastructure gives you.
So when you need raw treatment of a http request, use a handler instead of a page.
I've made a few screen copies while developing a very simple handler, so that you can see how easy it becomes to develop an ashx file in Visual Studio 2005 (click on the images to get them at full resolution):
Step 1
Step 1: Adding a new item to the project. I'm choosing "generic handler", which will create the ashx file with the code structure already there.
Step 2
Step 2: This is the code structure that Visual Studio provides. I did not write a single character at this point.
Step 3
Step 3: I have full IntelliSense and code coloring on my code. Everything works exactly the same as in any other code file.
Step 4
Step 4: I also have access to refactoring, immediate squiggly red lines under my syntax errors, etc.
Step 5
Step 5: I can build the page, the whole web site or the whole solution (or even just save and let the server auto-compile on the first request).
Step 6
Step 6: I can see build errors (I made stupid errors on purpose here, in real life I know how to initialize an array) and click on them to get to the faulty source code.
Step 7
Step 7: I'm almost done. The handler compiles.
Step 8
Step 8: And it works perfectly!
Update: Scott Hanselman has a great HttpHandler template to get you started.
More Posts