Migrating to the GridView and ObjectDataSource
I "adopted" a small app recently written in .NET 1.1, which I migrated to .NET 2.0 painlessly. It's only about 16 pages and user controls, so I wasn't expecting too many problems with the actual migration into VS 2005, and had none.
Of course, there's a difference between an app that runs against .NET 2.0 and a true .NET 2.0 app. To this end, I converted the main table of data on one of the main pages from a DataGrid
to a GridView
control. This too was rather painless--mainly replacing "Column" and "Item" in class/property names with "Field" and "Row".
Converting it from doing data binding manually in code to using an ObjectDataSource
in markup was a bit more work, though. Deleting automatically was a dream--I specified the delete method we already had, and removed the code that manually implemented delete against the DataGrid from the code-behind, and that was all it took. (This, I might add, has been my overall experience with ASP.NET 2.0--add a new feature like a master page or theme to your web site, delete a bunch of code--which is a lot
of fun.) However, for selecting data to display in the table, I ran into some surprises, as well as when implementing sorting, which was one of the new features I was adding to the app during this development cycle.
- A pattern used in this app is lightweight objects used mainly to store data, and separate objects to encapsulate the logic to instantiate these objects from database query results. As far as I could determine from the docs and Google searches, the ObjectDataSource doesn't support this. If you want to bind custom objects, you must do so using a method on the same class that you use to store the data, and specify that class using the TypeName property
. To me this seemed a bit short-sighted; why doesn't the ObjectDataSource take two class names, one for the type to be bound, and another for the class with the method(s) to do so, which defaults to the bound type if you don't specify it? I created a short method on my lightweight class that just calls the other method, and it worked fine.
- One thing touted about the GridView over the DataGrid was how easy sorting and paging and so forth go. Sure, the DataGrid supports sorting and paging, one developer evangelist told a large group of us, but you have to write much of the code to do the sorting and paging yourself. With the GridView, you get it free. Well, not in this case. Turn on sorting, click on a column header, and it gives you this (very helpful and descriptive, at least) exception:
[NotSupportedException: The data source 'MyDataSource' does not support sorting with IEnumerable data. Automatic sorting is only supported with DataView, DataTable, and DataSet.]
System.Web.UI.WebControls.ObjectDataSourceView.CreateEnumerableData(Object dataObject, DataSourceSelectArguments arguments) +425
System.Web.UI.WebControls.ObjectDataSourceView.ExecuteSelect(DataSourceSelectArguments arguments) +2652
System.Web.UI.DataSourceView.Select(DataSourceSelectArguments arguments, DataSourceViewSelectCallback callback) +13
System.Web.UI.WebControls.GridView.OnPreRender(EventArgs e) +24
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5731
So not only did I have to write a pass-through method to the one I already had to retrieve the data, I now had to change it from a simple pass-through to duplicate the functionality of my original select method, returning a DataTable instead of a custom collection. Once I did that, I did get my sorting without additional work, but it was disappointing that it couldn't sort my custom collection without me writing a manual sort method; I had hoped it would just sort the data after pulling it out of the collection, the same way we'd sort any list of numbers or strings.
This supports my initial impression of the new ObjectDataSource, SqlDataSource, etc. classes, that while it might be great for people who are more comfortable w/ XML/HTML markup than with C# code, it's not something I'm going to use everywhere in my applications instead of binding data with a couple lines of C# code. I'm far from writing them off, though, especially if they're used widely enough that they get filled out a bit more in future versions of .NET.