Data binding is one of the most powerful features of ASP.Net and Visual Studio. You can literally create an application with controls that are data bound to a database with only drag-and-drop and using simple wizards. However, with AJAX features your web application could refresh just its data instead of the whole page. Visual Studio does not offer much support for these more advanced features. This article will explain how to use Backbase data binding in combination with Visual Studio data binding.
Prerequisites and Intended Audience
Backbase Prerequisites
- Backbase Client Framework
- Intermediate level experience with the Backbase Client Framework
ASP.Net Prerequisites
- Microsoft .Net Framework v2.0 or higher
- Microsoft Visual Studio 2005 or similar
- Intermediate level experience with ASP.Net
Local vs. Remote Data Binding
In general, two approaches are available to data binding: local and remote.
Local Data Binding
With local data binding, you make sure that all the data that the user is able to see in this particular context is already available on the client (with Backbase, this is typically in XML format). Using data filters, the user may be limited to viewing only a small part of that data at the time, though all data should already be available in the browser. The client-side application code selects the data to be displayed from the client-side dataset.
The advantage of this approach is that users can get immediate feedback on their filter selection. For example, think of a slider to select only hotels in a certain price or quality range. Local data binding will result in the best user experience for small datasets. Unfortunately, this situation is not that common. The data filters are most necessary with large datasets, where the initial loading time of the page/application may become too much of a hassle for the user.
Remote Data Binding
With remote data binding, the visual controls/widgets are on the client side (within the browser), but the dataset remains on the server. Only the data that needs to be shown is available on the client. This is the most common solution for applications that use paging to show only small parts of the dataset. It is then up to the developer to use a simple pager or a more advanced solution like the liveGrid, though the concept remains the same.
The biggest advantage of remote data binding is obviously the short loading time. Only a small part of the data needs to be loaded. The disadvantage is that for every data refresh, additional client-server communication is needed. This could result in a slightly sluggish data refresh, even though it is still faster than in traditional web applications where the whole page would be refreshed. In the case of using the slider as a data filter, it will not work well, since the user will expect an immediate response while sliding.
Local Data Binding Example Application
We must first create an ASP.Net page that is using the Backbase engine: LocalListGrid.aspx.
For this example, we use an <asp:XmlDatasource />, because it is simpler to distribute, but you could just as easily use an <asp:SqlDatasource /> and link it to your own database tables. For local data binding, the <asp:Repeater /> is our key component. We use it to iterate over the dataSource and generate the desired page.
We have two options:
- Use the
<asp:Repeater />to generate the whole<b:dataSource />content that we will bind (client-side) to our widgets. - Use the
<asp:Repeater />to generate the visual controls/widgets, with the data as part of the widget.
A simple example of the second option would be to look at a table as a widget and generate all rows and cells with the data as content inside.
It this example, we go for the first option. It has the advantage that it can use the full Backbase data binding concept, with paging and so forth. Note that you may need to use the second option for Backbase widgets that do not yet support data binding, such as menus.
Our LocalListGrid.aspx file would look like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:e="http://www.backbase.com/2006/xel" xmlns:xi="http://www.w3.org/2001/XInclude">
<head runat="server">
<title>Untitled Page</title>
<script type="text/javascript" src="/Backbase_4_2_1/engine/boot.js"></script>
</head>
<body>
<form id="form1" runat="server">
<div id="loadingMessageContainer">
<div id="loadingMessage">Please wait while loading the application...</div>
</div>
<xmp backbase="true" e:onload="document.getElementById('loadingMessageContainer').style.display = 'none'" style="height:100%">
<xi:include href="/Backbase_4_2_1/bindings/config.xml" />
<asp:XmlDataSource ID="contacts" runat="server" DataFile="movies.xml" />
<div xmlns:b="http://www.backbase.com/2006/btl" xmlns:d="http://www.backbase.com/2006/tdl" xmlns:e="http://www.backbase.com/2006/xel" xmlns:smil="http://www.w3.org/2005/SMIL21/BasicAnimation" xmlns:bf="http://www.backbase.com/2007/forms" xmlns:c="http://www.backbase.com/2006/command" xmlns:xi="http://www.w3.org/2001/XInclude">
<asp:Label ID="Label1" runat="server" Font-Size="Large" Text="Databinding - Local"></asp:Label>
<b:listGrid id="myListGrid" width="auto" height="300px" readonly="true" rows="10">
<b:dataSource e:behavior="b:localData" dataType="application/xml">
<b:dataContainer>
<movies xmlns="">
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="contacts">
<ItemTemplate>
<contact>
<title><%# XPath("title") %></title>
<genre><%# XPath("genre") %></genre>
<rating><%# XPath("rating") %></rating>
</contact>
</ItemTemplate>
</asp:Repeater>
</movies>
</b:dataContainer>
</b:dataSource>
<b:listGridCol select="title" label="Title" width="200px"></b:listGridCol>
<b:listGridCol select="genre" label="Genre" width="100px"></b:listGridCol>
<b:listGridCol select="rating" label="Rating" width="70px" align="right"></b:listGridCol>
</b:listGrid>
<b:pagerBar width="auto">
<b:pager for="id('myListGrid')" width="250px">
<b:pagerButton type="First" />
<b:pagerButton type="Previous" />
<b:pagerSeparator />
<b:pagerJumper />
<b:pagerSeparator />
<b:pagerButton type="Next" />
<b:pagerButton type="Last" />
</b:pager>
</b:pagerBar>
</div>
</xmp>
</form>
</body>
</html>
Additionally, we use the following local XML source file called movies.xml:
<movie id="film-0" open="true" hasChildren="true">
<new></new>
<title>The Seven Samurai</title>
<genre>Drama</genre>
<rating>88</rating>
</movie>
<movie id="film-1" parentId="film-0">
<new><img src="examples/media/new.gif" width="12" height="12" alt="New" /></new>
<title>City of God</title>
<genre>Drama</genre>
<rating>88</rating>
</movie>
<movie id="film-2" parentId="film-0">
<new></new>
<title>The Godfather</title>
<genre>Crime</genre>
<rating>91</rating>
</movie>
<movie id="film-3" hasChildren="true">
<new><img src="examples/media/new.gif" width="12" height="12" alt="New" /></new>
<title>The Thin Red Line</title>
<genre>War</genre>
<rating>73</rating>
</movie>
<movie id="film-4" parentId="film-3" hasChildren="true">
<new></new>
<title>Scarface</title>
<genre>Crime</genre>
<rating>80</rating>
</movie>
<movie id="film-5" parentId="film-4" hasChildren="true">
<new><img src="examples/media/new.gif" width="12" height="12" alt="New" /></new>
<title>Carlito's Way</title>
<genre>Crime</genre>
<rating>76</rating>
</movie>
<movie id="film-6" parentId="film-5" hasChildren="true">
<new></new>
<title>Apocalypse Now</title>
<genre>War</genre>
<rating>85</rating>
</movie>
<movie id="film-7" parentId="film-6">
<new><img src="examples/media/new.gif" width="12" height="12" alt="New" /></new>
<title>Red Eye</title>
<genre>Thriller</genre>
<rating>66</rating>
</movie>
<movie id="film-8" parentId="film-6">
<new><img src="examples/media/new.gif" width="12" height="12" alt="New" /></new>
<title>Sin City</title>
<genre>Action</genre>
<rating>84</rating>
</movie>
<movie id="film-9" parentId="film-5">
<new></new>
<title>The Shawshank Redemption</title>
<genre>Drama</genre>
<rating>92</rating>
</movie>
<movie id="film-10" parentId="film-4">
<new></new>
<title>Casablanca</title>
<genre></genre>
<rating>87</rating>
</movie>
<movie id="film-11" parentId="film-4">
<new></new>
<title>Star Wars</title>
<genre>Adventure</genre>
<rating>88</rating>
</movie>
<movie id="film-12" parentId="film-3">
<new><img src="examples/media/new.gif" width="12" height="12" alt="New" /></new>
<title>Pulp Fiction</title>
<genre>Crime</genre>
<rating>88</rating>
</movie>
<movie id="film-13" hasChildren="true">
<new><img src="examples/media/new.gif" width="12" height="12" alt="New" /></new>
<title>Alone in the Dark</title>
<genre>Action</genre>
<rating>9</rating>
</movie>
<movie id="film-14" parentId="film-13">
<new><img src="examples/media/new.gif" width="12" height="12" alt="New" /></new>
<title>Memento</title>
<genre>Thriller</genre>
<rating>86</rating>
</movie>
<movie id="film-15" hasChildren="true">
<new></new>
<title>Psycho</title>
<genre>Horror</genre>
<rating>86</rating>
</movie>
<movie id="film-16" parentId="film-15">
<new><img src="examples/media/new.gif" width="12" height="12" alt="New" /></new>
<title>American Beauty</title>
<genre>Drama</genre>
<rating>85</rating>
</movie>
<movie id="film-17" parentId="film-15" hasChildren="true">
<new></new>
<title>Eternal Sunshine of the Spotless Mind</title>
<genre>Drama</genre>
<rating>85</rating>
</movie>
<movie id="film-18" parentId="film-17">
<new><img src="examples/media/new.gif" width="12" height="12" alt="New" /></new>
<title>Lost in Translation</title>
<genre>Drama</genre>
<rating>79</rating>
</movie>
<movie id="film-19" parentId="film-15">
<new></new>
<title>Battle Royale</title>
<genre>Action</genre>
<rating>80</rating>
</movie>
</movies>
The LocalListgrid.aspx Explained
We want to use the powerful ASP.Net data sources. In the example above, we usec the <asp:XmlDatasource /> and simply loaded a data XML file:
<asp:XmlDataSource ID="contacts" runat="server" DataFile="movies.xml" />
Next, we define the Backbase listGrid widget:
<b:dataSource e:behavior="b:localData" dataType="application/xml">
<b:dataContainer>
<movies xmlns="">
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="contacts">
<ItemTemplate>
<contact>
<title><%# XPath("title") %></title>
<genre><%# XPath("genre") %></genre>
<rating><%# XPath("rating") %></rating>
</contact>
</ItemTemplate>
</asp:Repeater>
</movies>
</b:dataContainer>
</b:dataSource>
<b:listGridCol select="title" label="Title" width="200px"></b:listGridCol>
<b:listGridCol select="genre" label="Genre" width="100px"></b:listGridCol>
<b:listGridCol select="rating" label="Rating" width="70px" align="right"></b:listGridCol>
</b:listGrid>
Note two things here:
- Do not let the fact that we use a server-side XML Datasource and a client-side XML Datasource confuse you. We could just as easily use an
<asp:SqlDataSource />server-side and create the client-side XML datasource using its data. - We have the
<b:dataSource />inline here in the<b:listGrid />for convenience, but it could be anywhere in our page and linked using thedataSourceattribute.
As part of our listGrid, we specify the colomns. The select attribute on each column determines the value from the dataSource that we want to show in this column.
Finally, we add a pager for the listGrid:
<b:pager for="id('myListGrid')" width="250px">
<b:pagerButton type="First" />
<b:pagerButton type="Previous" />
<b:pagerSeparator />
<b:pagerJumper />
<b:pagerSeparator />
<b:pagerButton type="Next" />
<b:pagerButton type="Last" />
</b:pager>
</b:pagerBar>
Since we are using a Backbase dataSource here, the pager and listGrid are smart enough to show only the desired records on one page, and when we iterate through the page, update the data from the client-side dataset!
Remote Data Binding Example Application
For clarity, our second example is almost exactly the same, except that we will use remote data binding.
The remote data binding example uses two files: RemoteListGrid.aspx and RemoteDataSource.aspx.
RemoteListGrid.aspx
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:e="http://www.backbase.com/2006/xel" xmlns:xi="http://www.w3.org/2001/XInclude">
<head runat="server">
<title>Untitled Page</title>
<script type="text/javascript" src="/Backbase_4_2_1/engine/boot.js"></script>
</head>
<body>
<form id="form1" runat="server">
<div id="loadingMessageContainer">
<div id="loadingMessage">Please wait while loading the application...</div>
</div>
<xmp backbase="true" e:onload="document.getElementById('loadingMessageContainer').style.display = 'none'" style="height:100%">
<xi:include href="/Backbase_4_2_1/bindings/config.xml" />
<b:dataSource name="moviesDataSource"
dataType="application/xml"
url="remotedatasource.aspx"
method="GET"
dataSelect="//movies/*"
e:behavior="b:remoteData">
</b:dataSource>
<div xmlns:b="http://www.backbase.com/2006/btl" xmlns:d="http://www.backbase.com/2006/tdl" xmlns:e="http://www.backbase.com/2006/xel" xmlns:smil="http://www.w3.org/2005/SMIL21/BasicAnimation" xmlns:bf="http://www.backbase.com/2007/forms" xmlns:c="http://www.backbase.com/2006/command" xmlns:xi="http://www.w3.org/2001/XInclude">
<asp:Label ID="Label1" runat="server" Font-Size="Large" Text="Databinding - Remote"></asp:Label>
<b:listGrid id="myListGrid" width="auto" height="300px" readonly="true" rows="10" dataSource="moviesDataSource">
<b:listGridCol select="title" label="Title" width="200px"></b:listGridCol>
<b:listGridCol select="genre" label="Genre" width="100px"></b:listGridCol>
<b:listGridCol select="rating" label="Rating" width="70px" align="right"></b:listGridCol>
</b:listGrid>
<b:pagerBar width="auto">
<b:pager for="id('myListGrid')" width="250px">
<b:pagerButton type="First" />
<b:pagerButton type="Previous" />
<b:pagerSeparator />
<b:pagerJumper />
<b:pagerSeparator />
<b:pagerButton type="Next" />
<b:pagerButton type="Last" />
</b:pager>
</b:pagerBar>
</div>
</xmp>
</form>
</body>
</html>
RemoteDataSource.aspx
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Xml.XPath" %>
<script runat="server">
public void Page_Load(Object sender, EventArgs E)
{
int page = Int32.Parse(Request.QueryString.Get("page"));
int rows = Int32.Parse(Request.QueryString.Get("rows"));
XmlDocument document = new XmlDocument();
document.Load(this.MapPath("") + @"\movies.xml");
XmlDocument resultDocument = new XmlDocument();
XmlElement root = resultDocument.CreateElement("movies");
resultDocument.AppendChild(root);
XPathNavigator navigator = document.CreateNavigator();
int recordCounter = 0;
foreach (XPathNavigator nav in navigator.Select("//movies/*"))
{
if ((recordCounter >= ((page - 1) * rows)) && (recordCounter < (page * rows)))
{
XmlElement movieElement = resultDocument.CreateElement("movie");
root.AppendChild(movieElement);
XmlElement titleElement = resultDocument.CreateElement("title");
movieElement.AppendChild(titleElement);
titleElement.InnerText = nav.SelectSingleNode("title").Value;
XmlElement genreElement = resultDocument.CreateElement("genre");
movieElement.AppendChild(genreElement);
genreElement.InnerText = nav.SelectSingleNode("genre").Value;
XmlElement ratingElement = resultDocument.CreateElement("rating");
movieElement.AppendChild(ratingElement);
ratingElement.InnerText = nav.SelectSingleNode("rating").Value;
}
recordCounter++;
}
XmlAttribute att = resultDocument.CreateAttribute("_actions_");
att.Value = "true";
root.Attributes.Append(att);
XmlElement totalsElement = resultDocument.CreateElement("read");
root.AppendChild(totalsElement);
XmlAttribute att2 = resultDocument.CreateAttribute("totalRecords");
att2.Value = recordCounter.ToString();
totalsElement.Attributes.Append(att2);
Response.Write(resultDocument.OuterXml);
}
</script>
The RemoteListGrid.aspx Explained
With remote data binding, all the data is retrieved by additional client-server communication and they are all initiated by the client. That is why our page with the listGrid on it no longer needs the server-side dataSource defined, the repeater, and so forth. We simply have a page with the listGrid, pager and – very important - the client-side dataSource definition:
dataType="application/xml"
url="remotedatasource.aspx"
method="GET"
dataSelect="//movies/*"
e:behavior="b:remoteData">
</b:dataSource>
In this example, the e:behavior attribute tells the Backbase Client Framework that this dataSource is remote, the url attribute tells it where the data can be found, and the dataSelect attribute uses XPath to select the relevant data from our XML response.
It is important to know that Backbase is using a small communication protocol for remote databinding. You should check the Backbase documentation for details. Here we only focus on what is interesting for our example: page numbers and totalRecords. Obviously, remote data binding is mainly interesting for large datasets that are often shown using paging. In every request for data, the client passes the page (or data chunk) that needs it to load. In the response, the server passes the total number of records to enable the client to show how many pages are available, and enables/disables the next page buttons, and so forth.
To retrieve the data, we created a simple ASP.Net page (RemoteDataSource.aspx) without controls on it or code behind the file. This is just a simple file for loading the XML data and iterating over it using XPath, and a foreach loop to create the correct response XML document. At the end, the totalRecords attribute is added and the XML is returned to the client with a simple Response.Write.
Summary
In this example, we have shown you the concept of Backbase data binding in combination with ASP.Net. You can choose between generating local data using ASP.Net data binding and remote data with paging using an XML response produced by an ASP.Net page.
