Using ObjectDataSource to do the dirty work for your custom data source

Since ASP.NET 2.0 was released in 2005 many of you have taken advantage of the new data source control controls. Drop a GridView on the page. Bind it to a data source. Check a few checkboxes. Run the page. Go home early!

However, some of you want to take data sources a step further. I've recently been chatting with Tobias Hertkorn on his blog about Trying to enhance ObjectDataSource. I figured I'd take advantage of Windows Live Writer to make a nice looking blog post about some neat techniques you can use to enhance the ObjectDataSource control. Tobi is trying to derive from ObjectDataSource to add some new and much simplified functionality for his users.

Sure enough, Tobi encountered problems taking advantage of ObjectDataSource to do the dirty work of data source architecture. My response mostly boiled down to "this type of extensibility was not what we had in mind for ObjectDataSource" and "We felt that if you need this degree of customization that writing your own data source is not that much of a stretch."

While I'm not taking back those statements, there are still a lot of neat things you can do with ObjectDataSource. For example, let's say you want to have a friendly data source that lets you choose from some simple sources of data instead of requiring users to select a type name and a select method. Following is the all new eStuff Sample FoodDataSource. The FoodDataSource has just one required property: FoodType. You pick the FoodType, and the FoodDataSource figures out what data to return. Pretty simple, isn't it?

namespace eStuff.Samples {
    using System.Collections;
    using System.Web.UI;
    using System.Web.UI.WebControls;

    public class FoodDataSource : ObjectDataSource {

        private string _foodType;

        public FoodDataSource()
            : base(typeof(FoodData).FullName, "GetFood") {
            // Constructor parameters:
            // - ObjectDataSource complains if we don't have a TypeName set.
            // - Our custom object's SelectMethod is always called GetFood.

            // Hook up the ObjectCreating event so we can use our custom object
            ObjectCreating += delegate(object sender, ObjectDataSourceEventArgs e) {
                // Here we create our custom object that the ObjectDataSource will use
                e.ObjectInstance = new FoodData(this);
            };
        }

        // Public property for the user to choose their food type
        public string FoodType {
            get {
                return _foodType;
            }
            set {
                _foodType = value;
            }
        }

        // Custom data object that returns yummy foods
        private sealed class FoodData {
            private FoodDataSource _dataSource;

            public FoodData(FoodDataSource dataSource) {
                _dataSource = dataSource;
            }

            public IEnumerable GetFood() {
                string foodType = _dataSource.FoodType;
                yield return foodType + " yummy 1";
                yield return foodType + " yummy 2";
                yield return foodType + " yummy 3";
                yield return foodType + " yummy 4";
            }
        }
    }
}

And now a sample ASPX page that uses the data source:

<%@ Page Language="C#" %>

<%@ Register Namespace="eStuff.Samples" TagPrefix="eStuff" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Yummy Foods</title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <eStuff:FoodDataSource runat="server" ID="FoodData" FoodType="ice cream">
            </eStuff:FoodDataSource>
            <asp:GridView ID="FoodGrid" DataSourceID="FoodData" runat="server">
            </asp:GridView>
        </div>
    </form>
</body>
</html>

As you can tell from the page, using the FoodDataSource is indeed very simple. No need to worry about long type names and select methods! All the real work was even done in ObjectDataSource's constructor. By passing a reference to the FoodDataSource into the FoodData object, the FoodData object can lazily decide what data it wants to return from its SelectMethod ("GetFood"). My initial version of this control was quite hacky about how and when it knew what data to return. But I ended up with this rather clean approach that doesn't violate and philosophical or technical rules about writing controls.

Have any of you adapted the ObjectDataSource to do your dirty work? Did you run into any problems?

15 Comments

  • The .NET 2.0 ObjectDataSource is, um, sweet.
    I used it with Ajax to upgrade an ASP 3 set of records from SQL Server 2005 and they not only load faster, much faster, for the client but are also easier to browse via a dropdown control. . .stunning indeed.

  • Or why not use a ORM tool such as LLBLGen or NHibernate that generates the DataSourceControl for you and you can go home at lunch?!?!? ;)

  • I second Richard's comment. I use .netTiers to do the same thing :-)

  • Unfortunately for me, coming from VB6 to VB.NET, it is very difficult to convert this to VB.

    I tried an online converter, but it had numerous syntactical challenges it couldn't overcome and I am not facile enough with the language/framework to correct the problems.

    Do you have a VB.NET version of this code?

  • Hello there, Eilon.

    I'm not new at C#, but lately I've taken to working with data by using DataSources, Adapters and everything else. After a few days of development, a question hit me - what's the purpose of an ObjectDataSource if you've already created your table adapters and business objects which provide the logic behind fetching data?

    Rowan

  • Hi Rowan,
    The idea behind the ObjectDataSource is that, as you've discovered, it doesn't do any data access at all. It never connects to a database and it never updates any rows. The reason we have ObjectDataSource is to enable declarative databinding between data bound controls (for example, GridView, FormView, and DetailsView) and your business object. Without ObjectDataSource you'd have to handle a variety of events on the page and on the data bound control to ensure you hook them up correctly and pass the data around.

    Thanks,
    Eilon

  • i have fetching the particular data's from data grid to textboxes.Here fetching the data's should be using checkboxes.

  • I'm convinced the objectdatasource doesn't work like it's supposed to, but I'm having difficulty finding a workaround for the update method. Still stuck at "Could not find a property named '' on the type specified by the dataobjecttypename property.

  • Hi Ken,
    What property can't it find? The ObjectDataSource requires a public get/set property that matches the name of the field you're trying to update. For example, if the field name is CustomerName and the data object is of type MyCustomer, you need to have:

    public class MyCustomer {
    public string CustomerName { get; set; }
    }

    Thanks,
    Eilon

  • I'm approaching this through vb.net; I haven't formally declared the objectdatasource through code. I thought the idea was that I configured the typed dataset, and wired it through the objectdatasource.

    I've enabled paging on the objectdatasource and that's all working with select method, but when I attempt an update, I get the message referred to above ("could not find the property named [first column in control] on the type specified...

    Here's my Objectdatasource ASP.NET code.

















    Do I really have to write a property for every parameter? Your comment indicates I'm missing a property on the objectdatasource. However, the error message specifies that the location where the property cannot be found is in the typed dataset.
    I'd like to find some example code showing it all put together.

    Thanks...

  • The problem I am having is the way that ObjectDataSource is when passing in a DataSet. The selection works great, but the update requires a method on the object that has all the parameters in the updated row... why not just return a DataRow? This makes it impossible for me to use a generic object over different tables. I even tried to use the params keyword to allow a variable parameter list and it still barfs. Very frustrating.

  • hi,

    I'm having trouble getting this code to work. I've copied the code at the top of the page verbatim but when run i get the following error:

    Parser Error Message: Unknown server tag 'eStuff:FoodDataSource'.

    Source Error:


    Line 10:
    Line 11:
    Line 12:
    Line 13:
    Line 14:

    Can someone please let me know if there is an erro with the original code or is there soomething the code reqwuires that I'm not aware of?

  • Nik - You need to include a tag mapping either in web.config (http://msdn.microsoft.com/en-us/library/ms164641.aspx) or in a directive in the page. If you look closely it's shown in the code sample:



    Thanks,
    Eilon

  • I'm getting the same error
    Unknown server tag 'eStuff:FoodDataSource'.
    but I do have

    at the top of my page.

  • Same as the last two guys, unknown server tag 'eStuff:FoodDataSource' when I try to debug the aspx page ...

Comments have been disabled for this content.