Thursday, May 6, 2010

Showing temporary HTML UI between redirection and rending of web form

The scenario leading to this solution was:

The home page of my application takes almost 30 seconds. Sounds ridicules but during this time, the application makes 6 service calls using 2 services and from 4 different databases loading huge data in the cache and session. So that, any subsequent request will be very fast. That was the initial requirement before I started designing this application.

The login page loads up first. When the user logs in, the home page shows up, but - only after starring at the white browser screen for around 30 painful  seconds. So, we needed so show some kind of a UI to the user saying something on the lines of  “We’re validating your credentials please wait… thank you for your patience… here’s a flash puzzle you can solve in the mean time… ”.

I found this in action while searching for vacation packages or flights on sites like Orbit or Expedia. Even Microsoft’s Live team showed a little animation game while uploading files to skydrive.live.com. But, my initial google/bing showed no result.  Also, none of the following worked:

  • Response.Write()
  • <body onload=" ....">
  • jQuery’s $(document).ready()

Because, any of the above will be fired only after the page lifecycle of the requested page is complete. So we need to skip the page lifecycle. An obvious solution to this problem is use ASP.NET MVC (please!). But since my client had already decided against it, so that was not an option.

Here’s what worked:

Step 1 -

In the Login action’s event handler, after the authentication, redirect the user to an HTML page. This HTML page can have what ever UI you want to show (even a flash animation). While redirecting, pass the home page’s URL of the application as a query string parameter.

protected void LoginButton_Click(object sender, EventArgs e) {

    //Assuming that user was authenticated
    //Redirect to a temporary HTML page sending the home page URL in query string

    string appurl = @"/Home/DashBoard.aspx";
    Response.Redirect(@"/HTMLPage1.htm?appUrl=" + appurl);

}

Step 2 –

Create the HTML page with the intended UI. In the body tag’s onload handler of this page retrieve the url from the query string and redirect the user to that url using java script (setting window.location). Here’s the HTML page:

<!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>
    <title>Welcome to our application!</title>

    <script type="text/javascript">

        function pageLoad() {

            var url = location.search.substring(8, location.search.length);
            window.location = url;
        }
        
    </script>

</head>
<body onload="setTimeout('pageLoad()', 1);">
    <div style="background-color: #C1C1C1;text-align:center;">
        <h1>
            Welcome to our application!</h1>
        <br />
        <h5>
            This is a temporary HTML page we are showing you while we load and set up your dashboard.</h5>
        <h5>
            It might tale 20-30 seconds.</h5>
        <h5>
            We thank you for your patience.</h5>
        <h3>
            If I knew flash or silverlight better <i>(more like at all)</i>, I’d had put some animation here...</h3>
    </div>
</body>
</html>

You can download the demo solution here.

Wednesday, May 5, 2010

Telerik RAD Grid nested table view items

In my current project, we are using the Telerik RadControls for ASP.NET Ajax very heavily, specially the Telerik’s RadGrid.
I liked the product, the ease to implement and clean Ajaxification of all kind of server controls is cool.
However, while working with Telerik’s RadGrid a came across a couple of problems. Thanks to the Telerik support team those issues were answered and taken care of. But, before contacting them, I spend considerable time and effort trying to get a solution without success. So here is the information hidden deep in Telerik’s documentation.

We were trying to implement custom/programmatic  sorting, filtering  and grouping on Telerik’s RadGrid.
To do that we would need to grab the specific TableView (master or nested) and use the GetItems() method passing the Grid Item type specifying what you want.

First step - Grabbing the table view:
The following doesn’t work if you need to pull out the  FilteringItem out of a particular nested table view:

MyRadGrid.MasterTableView.DetailTables[0]

Here’s a generic method that I created and placed in the application specific Page base class:
protected GridTableView FindGridTableView(RadGrid radGrid, string tableViewName) {

    GridTableView nestedTableView = null;

    foreach (GridDataItem item in radGrid.Items) {

        if (item.OwnerTableView.Name == tableViewName) {
            nestedTableView = item.OwnerTableView;
            break;
        }
    }

    return nestedTableView;
}

Pretty self explanatory, given the grid instance and the table view name that you intend to find, this method will find and return irrespective of the nesting level.

Second step – Grabbing Grid Item through the table view:
And, this is how you get the filter or command items out of the nested table we just retrieved:

//using Telerik.Web.UI;
    
    //grab the Filtering Item
    GridFilteringItem filterAttr = (GridFilteringItem)tableView.GetItems(GridItemType.FilteringItem)[0];
    //file the filter command for a particular column 
    //(not going into how to set column values as you can get it pretty easily on telerik's site)
    filterAttr.FireCommandEvent("Filter", new Pair(column.CurrentFilterFunction.ToString(), column.UniqueName));
    
    //grabbing the command item
    GridCommandItem cmdItem = (GridCommandItem)tableView.GetItems(GridItemType.CommandItem)[0];
    //using Command Item
    (cmdItem.FindControl("MyDropDownList") as DropDownList).SelectedIndex = 0;
    
    // etc etc etc ...
The version of Telerik I used was - 2009.2.826.35.

On a side note, I would strongly recommend using ASP.NET MVC framework if you are looking to create highly ajaxified applications. If not MVC, the other way to go will be using Web Forms with WCF on the server with WebHttpBinding to make use of script and json support. This way you can make asynchronous calls to the service via java script surpassing the page life cycle when required…. but why use Web Forms if you you intend to surpass the page life cycle??? MVC is a very powerful framework made up all the goodies that you can imagine for today’s web application development.
Contact me if you want me to to explain this to you personally with a Demo.