Mapping business objects to ASPX pages

While going through the ASP.Net forums, I stumbled across a post where a guy asked:

I’m having trouble coming up with a good solution for programmatically mapping members of a business object to control elements on our UI. I’m wondering if someone else has done something similar and might have some useful suggestions.

My reply was a rather lengthy one in which I talked about an approach I recently used in the rewrite of my online baseball game, CSFBL. Since I eventually wanted to blog about this stuff, I figured I’ll just copy/paste the post I made on the forums below…


I struggled with this a bit (struggled in the sense that I couldn’t come to agreement with myself on how to do it!)… the following is what I settled on.

All my business objects are created using CodeSmith templates for Paul Wilson’s O/R mapper. I wanted the web interface to be able to use these directly from both the code-behind and the ASPX page. (Yes, I know the deal about allowing your presentation to be able to edit your data; I’m the only one working on the project, and I can easily refactor out that functionality to factory classes later.

The main reason the approach below worked on my project was because any given web page displayed the properties accessed through a single business object. For example, if this was a contact management web app (it isn’t), an instance of the Contact business class would be effectively “bound” to the ContactDetails.aspx web page. Note that the approach below can also be tailored to allow similar behavior with user controls (i.e. a user control is ‘bound’ to a specific business object).

To do all this required the creation of a few new classes in the web project.

The PageBase class overrides the default Page class, and adds one key function: a call to the page’s DataBind() method in the PreRender stage. This does two things: (1) it eliminates the need to call a DataBind() class in your page’s objects (at least I haven’t found anything that required otherwise), and (2) it enables us to bind in the ASPX (more on that soon).

public class PageBase : System.Web.UI.Page
{
 protected override void OnPreRender( EventArgs e )
 {
 this.DataBind();
 base.OnPreRender(e);
 }
}

The IDataView generic interface exposes a LoadData method and a simple “Data” property.

interface IDataView<t>
{
 T Data { get; }
 void LoadData();
}

The DataViewPage inherits our PageBase and implements the IDataView interface.

public abstract class DataViewPage : PageBase, IDataView
{
 private T _data;
 public T Data
 {
 get { return _data; }
 set { _data = value; }
 }

 protected override void OnInit( EventArgs e )
 {
 this.LoadData();
 if ( this._data == null )
 throw new DataLoadException("Unable to load data for the current page.");

 base.OnInit(e);
 }

 public abstract void LoadData();
}

Finally, a real web page. The web app itself is for a baseball game (the next iteration of CSFBL), so the sample below is the binding of a baseball league to the “LeagueAdmin” web page.

public partial class LeagueAdmin : DataViewPage
{
 public League League
 {
 get { return this.Data; }
 }

 public override void LoadData()
 {
 this.Data = League.RetrieveByKey(1);
 }
}

There’s a few key points to note on how I created the codebehind for the web page:

  • I exposed the Data property (which, thanks to generics, would still be the correct object type, in this case League) using a name other than Data (i.e. I used the property name League). This is merely for convenience and code readability.
  • The LoadData() method (from the interface) populates the Data property by loading from the business model (RetrieveByKey is a method on the League object that returns an instance of the League with the given key).

By doing this, I can do the following in my ASPX page:

Note that I used inline databinding < %# %> and not just < %= %>. The main reason for this is that the inline databinding does not get called until the OnPreRender event (remember our PageBase class?), which helps in situations where you have a postback that changes the business object data — by using databinding I was able to guarantee that this happened after any event-related data changes.

Now I don’t know if this is a great thing or a bad thing, but it definitely solved some problems for me. Oh, and note that all pages on the web site also work with viewstate turned off (another one of my requirements).

I hope I explained all that clearly!

0 thoughts on “Mapping business objects to ASPX pages

Leave a Reply to Tyre Cancel Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

This site uses Akismet to reduce spam. Learn how your comment data is processed.