Implementing two-way Data Binding for ASP.NET

How things work now

What's wrong with Data Binding in ASP.NET?

Unfortunately, I personally think that data binding in ASP.NET doesn't go nearly far enough. First the process of assigning data sources is cumbersome at best using either a slow and work extensive designer or alternately by having to embed yet another script based markup tag (<%# %>) into source code. Both are way too cumbersome if you're dealing with a lot of data on a regular basis.

But more importantly data binding in ASP.NET  is one way only. You can only bind data to data but there's no mechanism to unbind the data from the control back into its underlying datasource. It's hard to really call ASP.NET's mechanism data binding because really what it is is a data display mechanism.

To clarify though, there are really two types of data binding in ASP.NET. There's list based data binding of the type that you use to bind data to a ListBox or a DataGrid. This mechanism actually works very well and provides a good amount of flexibility. This is also primarily a display mechanism – you tend to display data or lists with this type of binding.

Then there is simple Control Data binding which basically binds to a single value to a property of a control. A text box binding to a field of the database is an example of simple data binding. This also tends to be the most common data binding that most people do during data entry and the one that is the most time consuming. And here is where the problem lies – the control binding here is one way and involves some convoluted syntax that isn't even property based.

The fact that data binding is one-way in ASP.NET is actually not all that surprising. The reason is that it's not easy to automatically bind back in Web applications, because it's very difficult in this stateless environment to tell exactly when data should be bound back to the underlying data source. After all on a Web page a lot of things need to happen in a specific order to re-establish state and there's no easy way to automatically know when a datasource is ready to receive the data without some logic as part of the application.

As you'll see in a minute my implementation skirts this particular issue by having the bind back operation occur manually through a call to a helper method or form method (if using an optional custom WebForm subclass).

How things work now

Let me give you an example to put the current process into perspective. Assume that I have a business form and want to display and edit some customer information. So I use my business object to load up a dataset with data from a Load() method which internally populates a DataSet and DataRow member (you could also do this manually in your code of course). I now have a Dataset that I can bind to the various controls. This is easily done by using the control's data binding options in the property sheet or by manually assigning the value using the ASP.NET data binding scripting syntax (yes another variation of <% %> syntax using <%# %>).  What's interesting is that the binding syntax is not property based but generates a chunk of ASP.NET script code that gets embedded into the HTML. The following binds to Company field of my DataRow for example:

<asp:TextBox id="txtCompany" runat="server" Width="285px"
            Text='<%# Customer.DataRow["company"] %>'></asp:TextBox>

You can enter that expression manually into the ASP.NET HTML document or you can use the builder that generates this expression automatically as shown in figure 1. This syntax is not exactly intuitive and obviously requires the ASP.NET script parser to parse the string first before ever assigning the data binding expression to be evaluated.

Figure 1 – Data binding dialog in ASP.NET lets you use custom expressions (shown here) or by selecting datasource from contained components that support the data binding interfaces.

Once bound to the data with this mechanism I can now display data in my Web Form. Then I want to edit the data in the various input controls and ASP.NET provides perfect state for doing the control based editing and posting. So if an error occurs I can display an error message or use an error provider to display the message without loosing my data for example. So far so good.

The next step is to save the data. When I click the save button some code is fired in the Web Form to save the data from the Web Form into my datasource, and then eventually back to the database. Although I've already told the control what data I want to bind to (how could you forget <%# Customer.DataRow["company"] %> after all), there's no automated way to bind the data back into the control. The reason for this should be clear – ASP.NET generated an actual value into the Text property, but really it never ‘bound' anything to the form.

So instead of simply unbinding the data I now have to write code like this for my business object or data source to handle the bind back:

Customer.DataRow["Company"] = this.txtCompany.Text;
Customer.DataRow["Address"] = this.txtAddress.Text;

Just about every data entry form will need this sort of code to bind data back. If the form has only a handful of controls this is no big deal, but if you have a heavy data entry form and many of these forms this gets to be a hassle. It's also a maintenance nightmare – every time you add a new control to the form you have to also add the code to post back the data – you now have to keep track of this in two separate places.  It gets worse when you need to bind back non-String data as you have to do type coercion and error handling:

try {
  Customer.DataRow["CustomerLevel"] =
              Int32.Parse(this.txtCustomerLevel.Text");
}
catch(Exception) {
  this.ErrorMsg  = this.ErrorMsg + "Invalid Customer Level";
}

I don't know about you, but this is a lot of repetitive work that I certainly don't want to do every time I bind back a form. There has to be a better way and there is.

You might also like...

Comments

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.” - Donald Knuth