Introduction
In this article I would like to examine two-way data-binding in 3-tier web application and how using XLib library can substantially decrease the amount of data-binding code without compromising the amount of control you have over it. I start by describing the ways data flow has been handled in 3-tier applications and how XLib improves upon it.
1 Binding Workflow
There are four common cases when data binding needs to be performed in 3-tier web application.
- Load record from database into business object
- Fill web controls on the web page with object properties
- Copy web control values into business object properties
- Save business object properties into database record
The simplest example for all the binding that occurs in 3-tier application would be updating data for a specific entity such as Customer. The steps are:
- Load appropriate record from table Customer
- Bind customer record to Customer business object
- Bind Customer object properties to web control values
- User enters information into form and clicks on submit
- Bind updated web control values to Customer object
- Bind Customer object to a table record
- Save table record to table Customer
There are multiple ways to implement this workflow. I will cover three:
- Explicit way of binding – know everything up front
- Microsoft Way – using Typed DataSet and FormView
XLib way – use reflection and other .NET features to analyze bind-able objects at run-time.
1.2 Code - Business Logic and Web Pages
To demonstrate all three approaches I will use a Customer class and a EditCustomer web page. Here is some code that indicates where all the data bindings occur:
In general, customer class will look like:
public class Customer
{
//list all properties
//CRUD methods
public void Load()
{
//Binding #1
//Copy database record values into properties
}
public void Save()
{
//Binding #4
//Copy properties values into database record
}
public void Delete() ;
//Other methods specific to customer
public string GetCustomerFullName()..
}
Edit Customer ASPX page will look like:
//Page headers and directives
//Form controls related to customer properties
//Submit/Cancel buttons to save information or go back
Edit Customer code-behind page will look like:
public partial class EditCustomer
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack){
//Check if adding new customer or updating
if (_isUpdateMode)
LoadData();
}
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
if (!Page.IsValid)
return;
SaveData();
//Go Back
}
private void LoadData()
{
Customer customer=new Customer();
customerID=_customerID;
customer.Load();
//Binding #2
//Copy customer properties into control values
}
private void SaveData()
{
Customer customer=new Customer();
If (_isUpdateMode)
{
customer.ID=_customerID;
customer.Load();
}
//Binding #3
//Copy control values into customer properties
customer.Save();
}
}
2. Three approaches to data binding
2.1 Approach #1: Explicit Way of Binding
One way to implement the Edit Customer scenario is to explicitly specify all the binding. This means that for each of four bindings – programmer would write out all the mappings. For example the Customer.Load method would look like:
public void Load()
{
…
//Load customer record using data reader
_firstName=(string)dataReader[“FirstName”];
_lastName=(string)dataReader[“LastName”];
…
}
The more properties exposed by the Customer object – the more lines of code you would have to write for each data binding. If you were to add a new property to customer – you would have to reflect that change in 6 places:
- Database
- Data Bind #1 – DB to Business Object
- Data Bind #2 – Business Object to Web Controls
- Web Form – add new control
- Data Bind #3 – Web Controls to Business object
- Data Bind #4 – Business Object to DB
As you can see the disadvantages to this approach are – bloated code and increased maintenance.
2.2 Approach #2: Microsoft Way - Typed DataSet and FormView
For this approach you could follow many examples that Microsoft has provided. If your application is simple enough – you can generate a typed data set from your Customer table and then use a FormView to add and edit Customer object. The tutorials on how to do it can be found at:
- Creating DAL using typed DataSets
- Modifying Data using FormView web control
For Database <=> Business object data binding – you generate the code using the typed data set wizard. For Business object <=> Web Controls data binding you need to insert web controls into InserItemTemplate and EditItemTemplate of a FormView control and specify all the binding rules using code like:
<asp:TextBox ID="txtLastName" Text='' RunAt="Server" />
As you probably have noticed with many Microsoft examples – they works really well for simple solutions, but for more complex solutions you have to keep adding workarounds till you get to a point where it would be easier to write your own code from scratch.
This approach simplifies maintenance versus the first solution. For example - if you need to add a new property to customer you need to do it in three places as opposed to six:
- Database
- Web Form –
EditItemTemplate
- Web Form –
InsertItemTemplate
On the other hand there is a lot of code duplication between
EditItemTemplate and
InsertItemTemplate. Also from my experience you lose a lot of flexibility when trying to specify complex object relationships using Typed DataSet.
2.3 XLib way of binding
XLib improves on both previous approaches by providing generic data binding for 90% of the cases, but also flexibility required for custom data manipulation. XLib uses reflection to automatically map object properties to database columns and web controls to object properties. It implements DB <=> Business Object binding using XbusinessObjectBinder object. Here is how it is used in the Customer object:
public class Customer
{
…
public void Load()
{
dataReader=new XDataReader();
//Load data using auto-generated query into XDataReader
//XDataReader works just like data reader – except it automatically
//converts Database values types into INulllable C# types
//Binding #1
XBusinessObjectBinder.FromDataReader(this, dataReader);
}
public void Save()
{
XDataWriter dataWriter=new XDataWriter();
//XDataWriter automatically generates INSERT/UPDATE/DELETE sql s
//statements
//Binding #4
XBusinessObjectBinder.ToDataWriter(this, dataWriter)
dataWriter.Update();
}
}
For binding Business Object <=> Web Controls - the XWebControlsBinder object is used. Here is what it looks like on the Edit Customer page:
public partial class EditCustomer
{
protected void Page_Load(object sender, EventArgs e)
{…}
protected void btnSubmit_Click(object sender, EventArgs e)
{…}
private void LoadData()
{
Customer customer=new Customer();
customerID=_customerID;
customer.Load();
//Binding #2
XWebControlsBinder.FromObject(this, customer);
}
private void SaveData()
{
Customer customer=new Customer();
if (_isUpdateMode)
{
customer.ID=_customerID;
customer.Load();
}
//Binding #3
//Copy control values into customer properties
XwebControlsBinder.ToObject(this, customer);
customer.Save();
}
}As you can see – this approach resembles approach #1, with the exception of replacing every code block responsible for data binding except every code with a single line of code. To simplify things even further
XLib implements the
XBusinessObject which automatically binds object properties to a database (just like an OR mapper). Internally it uses
XBusinessObjectBinder to do it. All you have to do is derive your class from
XBusinessObject and specify the
properties.
Summary
In this post we looked at various ways of implementing data binding in 3-tier web application and how XLib improves on more traditional approaches. XLib approach provides trade-of between total flexibility (Approach #1) and black box (Approach #2). You can implement 90% of the functionality using generic Binders included in XLib and just write custom code on top of it. In certain case you can bypass XLib altogether and use Approach #1.
| Data Binding Type |
Approach #1 Explicit Way |
Approach #2 Microsoft Way |
Approach #3 XLib Way |
| Data Record <=> Business Object |
Explicitly specify every data mapping from row field to business object property |
Typed data set |
XBusinessObjectBinder class |
| Business Object <=> Web Form |
Explicitly specify every mapping from Business Object property to web control value. |
FormView web control |
XWebControlsBinder class |
| Benefits |
- Total control over all data binding
|
- Can be very fast to implement and deploy for simple solutions.
|
- Uses one line of code for every data-binding scenario
- Supports binding nested objects
- Automatically implement CRUD using XbusinessObject (similar to OR mapper)
- Have access to all
XLib source-code |
| Disadvantages |
- Have to modify six places to add new property
- Slower development time – lots of copying and pasting (Note: can use Code Generator tool)
- Lots more code to maintain.
|
- Typed data sets may not be flexible enough for different types of object relationships
- Code duplication in FormView between
EditItemTemplate and InsertItemTemplate
- Web control data binding may not work if you have nested object ex. Customer.Address
|
- Learning curve for the first project using
XLib
- Supports all .NET and
XLib web controls, but need to add your own code for custom web controls or control tool kits.
- Performance is not as fast as the other two methods since reflection is being used. On the other hand, the difference in performance is negligible for vast majority of web applications.
|
References
XLib Library - download XLib, documentation
Web Controls binding - article about using reflection for binding web controls
Please login to rate or to leave a comment.