Ok, I ran into a major problem not so long ago. This problem stemmed from a DataObject that had a child object within it, here in referred to as a "complex object". When I put an ObjectDataSource on my page and bound to my business layer with my complex DataObject, for some reason only the simple properties would show up. Simple properties being those that are passed by value and of a .NET system type. My custom typed property never shows up in my data bound control. Hmmmmm...
After some research on complex objects and the ObjectDataSource, I found some examples of people adding the extra fields and type casting the Container.DataItem to expose the inner properties of the child object. This in turn would get them the data they needed. Then using the ObjectDataSource's OnUpdating or OnInserting event, they would then re-type cast the object while grabbing the values from the page and stick it into the dictionary of values in the event arguments. Whew! That is hard to explain, and in my opinion even uglier to look at! The biggest problem with that solution is that you will need to add in those event handlers on every web page that uses these complex objects. There has to be a better way.
There is, and it involves making some adjustments in the business layer and creating some shells for your complex objects. First let's build a data model. We will make a Person object that will contain a State object like so:
Now we need to make a presentation shell that gives us access to all the properties of Person, as well as giving us access to the properties of the State object within the Person object.
Here are the properties of our PersonPresentationShell object:
As you can see the PersonPresentationShell has a public field of Person. All the properties of it are just accessors of the Person object and the State object it contains. This makes for all of our properties being of .NET system types. Now let's have a look at the constructors:
As you can see, the first constructor just initializes the Person and State objects. This will be used by the ObjectDataSource to re-build our data. The second constructor will be the one we use when coating all our Person objects for presentation. Now we will have a look at our business logic:
You can see in the GetPeople method of the business layer, we get a list of Person from our data layer and convert them into a list of PersonPresentationShell and return them for display. Our Insert, Update and Delete methods all accept a PersonPresentationShell as an argument then pass the Person object it contains down into the data layer. Using this approach, put an ObjectDataSource on the page, configure it, and bind a GridView and a DetailsView to the data source and run the application.
Now all of the data controls work exactly as expected. It seems like a long way to go, but I feel like it is a pretty elegant solution. This ensures that my data and business layers have DataObjects for communication and my business layer and UI have PresentationShells for communication. All of the wrapping an unwrapping happens in one place, the business layer. Maybe in a future .NET release the ObjectDataSource will support "complex" objects.
If anyone has a better solution to this, please feel free to share!
Download the code:
ComplexDataObjects.zip (11.34 kb)