Progressive Enhancement of ASP.Net applications with Backbase

Many ASP.Net developers are faced with the following problem: people around you (customers or managers) are telling you website "X" has cool feature "Y" and they want you to include it in your websites. Usually this is about Rich Internet controls. However, replacing those controls is not always simple, since you are ‘stuck’ with the standard ASP.Net control set with no or limited dynamic behavior.

Replacing those ASP.Net controls in your existing code is not only a lot of work but also introduces the risk of introducing new bugs. If only you could quickly replace your controls with the nice Backbase controls with a minimal risk of breaking your application. Fortunately, Backbase enables you to do exactly this using a technique called ‘Progressive Enhancement’. This article will help you to get started doing this.

Prerequisites and Intended Audience

This example is intended for anyone interested in Ajaxifying existing ASP.Net applications using the Backbase Progressive Enhancement method.

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

What is Progressive Enhancement?

Progressive Enhancement – also called HTML Enhancement – is the technique to enhance your existing HTML pages with minimal code change. You only tell the Backbase Client Framework what rules it should use for the enhancement.

The Backbase enhancement process is as follows:

  • Your web server is executing your ASP.Net code and as a result returning an HTML page to the client browser. Note that the HTML page will include Backbase widgets (BTL in this case).
  • The browser loads this HTML page.
  • Like with any Backbase application, the JavaScript Client Engine is loaded and started.
  • The Client Engine parses the HTML / BTL to find the enhancement rules.
  • Based on the rules, it will replace HTML tags with Backbase widgets. Note that these HTML tags here are often not tags you wrote directly but generated based on your ASP.Net server controls.

As an example, this way we can easily enhance an ASP.Net DropDownList control:

Server Client Client after Enhancement
asp:DropDownList select b:comboBox

Usually, you will want to translate a whole group of controls into their Backbase counterparts. However, it would be too rudimentary to just always translate certain tags. That is why the enhancement rules use the notion of CSS classes to determine what tags to include in what enhancement rule.

Example Application

For this example, we assume that we have an existing ASP.Net form with some input controls on it. In this case, we use a simple form that requires you to enter some personal information:

PersonalInformation_Original.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="PersonalInformation_Original.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:Label ID="Label1" runat="server" Font-Size="Large" Text="Personal Information"></asp:Label>
            <div style="height:10px" />
            <table style="width: 100%">
                <tr>
                    <td style="height: 21px; width: 102px;">
                        <asp:Label ID="Label2" runat="server" Text="Name"></asp:Label></td>
                    <td style="height: 21px; width: 41px;">
                    </td>
                    <td style="height: 21px">
                        <asp:TextBox ID="NameTextBox" runat="server" Width="200px"></asp:TextBox></td>
                </tr>
                <tr>
                    <td style="height: 21px; width: 102px;">
                        <asp:Label ID="Label5" runat="server" Text="Sex"></asp:Label></td>
                    <td style="height: 21px; width: 41px;">
                    </td>
                    <td style="height: 21px">
                        <asp:DropDownList ID="DropDownList1" runat="server">
                            <asp:ListItem>Male</asp:ListItem>
                            <asp:ListItem>Female</asp:ListItem>
                        </asp:DropDownList></td>
                </tr>
                <tr>
                    <td style="width: 102px">
                        <asp:Label ID="Label3" runat="server" Text="Date of Birth"></asp:Label></td>
                    <td style="width: 41px">
                    </td>
                    <td>
                        <asp:TextBox ID="birthTextBox" runat="server" Width="200px"></asp:TextBox></td>
                </tr>
                <tr>
                    <td style="width: 102px">
                        <asp:Label ID="Label4" runat="server" Text="Age"></asp:Label></td>
                    <td style="width: 41px">
                    </td>
                    <td>
                        <asp:TextBox ID="ageTextBox" runat="server" Width="199px"></asp:TextBox></td>
                </tr>
            </table>
        <asp:Button ID="Button1" runat="server" Text="Submit" />
        </div>
    </form>
</body>
</html>

Enabling Backbase

The first step is to include the Backbase Engine in every page we want to enhance. You might consider creating a master page that deals with this, which you can re-use in your project if you have multiple pages that will require Progressive Enhancement. In this example, we will be using the following master page:

PersonalInformation_Backbase.master
<%@ Master Language="C#" AutoEventWireup="true" CodeFile="MyMPIPage.master.cs" Inherits="MPIPage" %>

<!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:contentplaceholder id="Content" runat="server" />
        </xmp>
    </form>
</body>
</html>

Next, since we are now using a master page, we have to modify our personal information form from a complete page to a content page for this master page. Therefore, we must strip everything around the form tag and put it inside an Asp:Content tag:

<%@ Page Language="C#" MasterPageFile="~/PersonalInformation_Backbase.master" AutoEventWireup="true"
    CodeFile="PersonalInformation_Backbase.aspx.cs" Inherits="_Default" %>


<asp:Content ContentPlaceHolderID="Content" runat="server">
    <div>
        <asp:Label ID="Label1" runat="server" Font-Size="Large" Text="Personal Information"></asp:Label>
        <div style="height: 10px" />
        <table style="width: 100%">
            <tr>
                <td style="height: 21px; width: 102px;">
                    <asp:Label ID="Label2" runat="server" Text="Name"></asp:Label></td>
                <td style="height: 21px; width: 41px;">
                </td>
                <td style="height: 21px">
                    <asp:TextBox ID="NameTextBox" runat="server" Width="200px"></asp:TextBox></td>
            </tr>
            <tr>
                <td style="height: 21px; width: 102px;">
                    <asp:Label ID="Label5" runat="server" Text="Sex"></asp:Label></td>
                <td style="height: 21px; width: 41px;">
                </td>
                <td style="height: 21px">
                    <asp:DropDownList ID="DropDownList1" runat="server">
                        <asp:ListItem>Male</asp:ListItem>
                        <asp:ListItem>Female</asp:ListItem>
                    </asp:DropDownList></td>
            </tr>
            <tr>
                <td style="width: 102px">
                    <asp:Label ID="Label3" runat="server" Text="Date of Birth"></asp:Label></td>
                <td style="width: 41px">
                </td>
                <td>
                    <asp:TextBox ID="birthTextBox" runat="server" Width="200px"></asp:TextBox></td>
            </tr>
            <tr>
                <td style="width: 102px">
                    <asp:Label ID="Label4" runat="server" Text="Age"></asp:Label></td>
                <td style="width: 41px">
                </td>
                <td>
                    <asp:TextBox ID="ageTextBox" runat="server" Width="199px"></asp:TextBox></td>
            </tr>
        </table>
        <asp:Button ID="Button1" runat="server" Text="Submit" />
    </div>
</asp:Content>

Now we can run it and check the result, which may not look very interesting, since it appears the same as the original form. However, you may have noticed the slight ‘flash’ of showing code. This shows us that the Backbase Client Framework is booting and busy parsing the code. Of course, this flash can easily be avoided in your final application.

Using Html Enhancement

The next step is to create the content page that will be placed in the ContentPlaceHolder, which contains the Progressive Enhancement:

PersonalInformation_Enhanced.aspx
<%@ Page Language="C#" MasterPageFile="~/PersonalInformation_Backbase.master" AutoEventWireup="true"
    CodeFile="PersonalInformation_Enhanced.aspx.cs" Inherits="_Default" %>


<asp:Content ContentPlaceHolderID="Content" runat="server">
<b:xhtml xmlns:b="http://www.backbase.com/2006/btl">
    <div >
        <asp:Label ID="Label1" runat="server" Font-Size="Large" Text="Personal Information"></asp:Label>
        <div style="height: 10px" />
        <table style="width: 100%" id="importTable">
            <tr>
                <td style="height: 21px; width: 102px;">
                    <asp:Label ID="Label2" runat="server" Text="Name"></asp:Label></td>
                <td style="height: 21px; width: 41px;">
                </td>
                <td style="height: 21px">
                    <asp:TextBox ID="NameTextBox" runat="server" Width="200px" CssClass="textinput"></asp:TextBox></td>
            </tr>
            <tr>
                <td style="height: 21px; width: 102px;">
                    <asp:Label ID="Label5" runat="server" Text="Sex"></asp:Label></td>
                <td style="height: 21px; width: 41px;">
                </td>
                <td style="height: 21px">
                    <asp:DropDownList ID="DropDownList1" runat="server" CssClass="comboinput">
                        <asp:ListItem class="comboinputitem">Male</asp:ListItem>
                        <asp:ListItem class="comboinputitem">Female</asp:ListItem>
                    </asp:DropDownList></td>
            </tr>
            <tr>
                <td style="width: 102px">
                    <asp:Label ID="Label3" runat="server" Text="Date of Birth"></asp:Label></td>
                <td style="width: 41px">
                </td>
                <td>
                    <asp:TextBox ID="birthTextBox" runat="server" Width="200px" CssClass="dateinput"></asp:TextBox></td>
            </tr>
            <tr>
                <td style="width: 102px">
                    <asp:Label ID="Label4" runat="server" Text="Age"></asp:Label></td>
                <td style="width: 41px">
                </td>
                <td>
                    <asp:TextBox ID="ageTextBox" runat="server" Width="199px" CssClass="sliderinput"></asp:TextBox></td>
            </tr>
        </table>
        <asp:Button ID="Button1" runat="server" Text="Submit" />
    </div>
    </b:xhtml>
       <div id="ctlEnhanceHTML" xmlns:b="http://www.backbase.com/2006/btl">

            <b:enhanceHTML select="javascript:document.getElementById('importTable')" rules="enhanceRules"   children="true"/>
            <b:enhanceHTMLRuleSet name="enhanceRules" xmlns:b="http://www.backbase.com/2006/btl">
                <b:enhanceHTMLRule name="textinput" ns="http://www.w3.org/1999/xhtml" localName="input" template="true">
                    <b:enhanceHTMLAttribute name="*" />
                </b:enhanceHTMLRule>
                <b:enhanceHTMLRule name="comboinput" ns="http://www.backbase.com/2006/btl" localName="comboBox"
                    template="true">

                    <b:enhanceHTMLAttribute name="width" value="100" force="true" />
                    <b:enhanceHTMLAttribute name="*" />
                </b:enhanceHTMLRule>
                <b:enhanceHTMLRule name="comboinputitem" ns="http://www.backbase.com/2006/btl" localName="comboBoxOption"
                    template="true">

                    <b:enhanceHTMLAttribute name="*" />
                </b:enhanceHTMLRule>
            </b:enhanceHTMLRuleSet>
        </div>
</asp:Content>
The PersonalInformation_Enhanced.aspx Explained

Below is a code snippet from the enhanced form:

<div id="ctlEnhanceHTML" xmlns:b="http://www.backbase.com/2006/btl">
        <b:enhanceHTML select="javascript:document.getElementById('importTable')" rules="enhanceRules" children="true"/>
        <b:enhanceHTMLRuleSet name="enhanceRules" xmlns:b="http://www.backbase.com/2006/btl">
                <b:enhanceHTMLRule name="textinput" ns="http://www.w3.org/1999/xhtml" localName="input" template="true">
                        <b:enhanceHTMLAttribute name="*" />
                </b:enhanceHTMLRule>
                <b:enhanceHTMLRule name="comboinput" ns="http://www.backbase.com/2006/btl" localName="comboBox" template="true">
                        <b:enhanceHTMLAttribute name="width" value="100" force="true" />
                        <b:enhanceHTMLAttribute name="*" />
                </b:enhanceHTMLRule>
                <b:enhanceHTMLRule name="comboinputitem" ns="http://www.backbase.com/2006/btl" localName="comboBoxOption" template="true">
                        <b:enhanceHTMLAttribute name="*" />
                </b:enhanceHTMLRule>
        </b:enhanceHTMLRuleSet>
</div>

In the second line, we declare the actual command to perform the enhancement. The select attribute points to the HTML element that we want to enhance (including its children) and the rules attribute refers to the ruleset we should use. This ruleset is declared immediately after the b:enhanceHTML command. In every rule, we can specify the name of the CSS class to which the rule applies. The localName and ns specify the tag to which it will be translated.

In this example, we translate all tags with CSS class comboinput to the <b:comboBox /> tag (where b is the most common prefix for the BTL namespace). However, this is not sufficient, since the <b:comboBox /> tag requires <b:comboBoxOption /> tags as its children. Therefore, we have the next rule to do exactly this.

Note that we can copy attributes from the original tag or create additional attributes on the destination tag using the <b:enhanceHTMLAttribute /> tag.

Using b:xhtml

As you may have noticed, we have wrapped the form elements inside a <b:xhtml /> tag. This tag is designed to prevent its content from being parsed by the Backbase Client Framework.

The reason we need to prevent this is because we will be reconstructing the element using Progressive Enhancement. During this process, the enhanced element will get the same ID as the element it is replacing. Without the <b:xhtml /> tag, our form elements would already have been constructed and a duplicate build of the same instance would occur (based on the ID attribute), which will result in a warning message thrown by the Backbase Client Framework.

To ensure that the controls inside the <b:xhtml /> tag are sent back to the browser, we also enhance the normal XHTML input controls.

More Advanced HTML Enhancement

In the previous section, we showed the concept of HTML Enhancement. However, the example application was not that spectacular. But remember that you need not translate a control to its exact Backbase counterpart; you can do any kind of translation. In this last example, we convert a simple <asp:TextBox /> for entering your age into a nice spinner and we convert an <asp:DropDownList /> to select the number of children into a cool slider! All we need is the following rules, which are very similar to the rules in the previous section:

PersonalInformation_MoreEnhanced.aspx
<%@ Page Language="C#" MasterPageFile="~/PersonalInformation_Backbase.master" AutoEventWireup="true"
    CodeFile="PersonalInformation_MoreEnhanced.aspx.cs" Inherits="_Default" %>


<asp:Content ContentPlaceHolderID="Content" runat="server">
<b:xhtml xmlns:b="http://www.backbase.com/2006/btl">
    <div >
        <asp:Label ID="Label1" runat="server" Font-Size="Large" Text="Personal Information"></asp:Label>
        <div style="height: 10px" />
        <table style="width: 100%" id="importTable">
            <tr>
                <td style="height: 21px; width: 102px;">
                    <asp:Label ID="Label2" runat="server" Text="Name"></asp:Label></td>
                <td style="height: 21px; width: 41px;">
                </td>
                <td style="height: 21px">
                    <asp:TextBox ID="NameTextBox" runat="server" Width="200px" CssClass="textinput"></asp:TextBox></td>
            </tr>
            <tr>
                <td style="height: 21px; width: 102px;">
                    <asp:Label ID="Label5" runat="server" Text="Sex"></asp:Label></td>
                <td style="height: 21px; width: 41px;">
                </td>
                <td style="height: 21px">
                    <asp:DropDownList ID="DropDownList1" runat="server" CssClass="comboinput">
                        <asp:ListItem class="comboinputitem">Male</asp:ListItem>
                        <asp:ListItem class="comboinputitem">Female</asp:ListItem>
                    </asp:DropDownList></td>
            </tr>
            <tr>
                <td style="width: 102px">
                    <asp:Label ID="Label3" runat="server" Text="Date of Birth"></asp:Label></td>
                <td style="width: 41px">
                </td>
                <td>
                    <asp:TextBox ID="birthTextBox" runat="server" Width="200px" CssClass="dateinput"></asp:TextBox></td>
            </tr>
            <tr>
                <td style="width: 102px">
                    <asp:Label ID="Label4" runat="server" Text="Age"></asp:Label></td>
                <td style="width: 41px">
                </td>
                <td>
                    <asp:TextBox ID="ageTextBox" runat="server" Width="199px" CssClass="spinnerinput"></asp:TextBox></td>
            </tr>
            <tr>
                <td style="width: 102px">
                    <asp:Label ID="Label6" runat="server" Text="Children"></asp:Label></td>
                <td style="width: 41px">
                </td>
                <td>
                    <asp:DropDownList ID="DropDownList2" runat="server" CssClass="sliderinput">
                        <asp:ListItem class="sliderinputitem">0</asp:ListItem>
                        <asp:ListItem class="sliderinputitem">1</asp:ListItem>
                        <asp:ListItem class="sliderinputitem">2</asp:ListItem>
                        <asp:ListItem class="sliderinputitem">3</asp:ListItem>
                        <asp:ListItem class="sliderinputitem">4</asp:ListItem>
                        <asp:ListItem class="sliderinputitem">5</asp:ListItem>
                        <asp:ListItem class="sliderinputitem">Lots!</asp:ListItem>
                    </asp:DropDownList></td>
            </tr>
           
        </table>
        <asp:Button ID="Button1" runat="server" Text="Submit" />
    </div>
    </b:xhtml>
       <div id="ctlEnhanceHTML" xmlns:b="http://www.backbase.com/2006/btl">

            <b:enhanceHTML select="javascript:document.getElementById('importTable')" rules="enhanceRules"   children="true"/>
            <b:enhanceHTMLRuleSet name="enhanceRules" xmlns:b="http://www.backbase.com/2006/btl">
                <b:enhanceHTMLRule name="textinput" ns="http://www.w3.org/1999/xhtml" localName="input" template="true">
                    <b:enhanceHTMLAttribute name="*" />
                </b:enhanceHTMLRule>
                <b:enhanceHTMLRule name="comboinput" ns="http://www.backbase.com/2006/btl" localName="comboBox"
                    template="true">

                    <b:enhanceHTMLAttribute name="width" value="100" force="true" />
                    <b:enhanceHTMLAttribute name="*" />
                </b:enhanceHTMLRule>
                <b:enhanceHTMLRule name="comboinputitem" ns="http://www.backbase.com/2006/btl" localName="comboBoxOption"
                    template="true">

                    <b:enhanceHTMLAttribute name="*" />
                </b:enhanceHTMLRule>
                <b:enhanceHTMLRule name="spinnerinput" ns="http://www.backbase.com/2006/btl" localName="spinner"
                    template="true">

                    <b:enhanceHTMLAttribute name="min" value="18" force="true"/>
                    <b:enhanceHTMLAttribute name="max" value="99" force="true"/>
                    <b:enhanceHTMLAttribute name="*" />
                </b:enhanceHTMLRule>
                <b:enhanceHTMLRule name="sliderinput" ns="http://www.backbase.com/2006/btl" localName="slider"
                    template="true">

                    <b:enhanceHTMLAttribute name="*" />
                </b:enhanceHTMLRule>
                <b:enhanceHTMLRule name="sliderinputitem" ns="http://www.backbase.com/2006/btl" localName="sliderOption"
                    template="true">

                    <b:enhanceHTMLAttribute name="*" />
                </b:enhanceHTMLRule>
            </b:enhanceHTMLRuleSet>
        </div>
</asp:Content>

For another HTML Enhancement example, refer to the importHtml demo in the Backbase Client Framework distribution. It is not using ASP.Net and it may seem a bit complex at first, but after the simpler examples described here, you should be able to understand the code. Now it is up to you to be creative and think of all the advanced possibilities for your own web applications.

Additional Resources