Click here to Skip to main content
Click here to Skip to main content

Web Page Loading in Steps - ASP.NET Solution

By , 23 Nov 2009
 
Prize winner in Competition "Best ASP.NET article of November 2009"

Table Of Contents

Introduction

Based on the [1] article, especially the section “Break UI Loading into Multiple Stages”, I decided to write a reusable ASP.NET control doing the mentioned functionality. As usual in my articles, you can see the live demo here.

The article also tries to explain the architecture and point out to other solutions.

I assume the reader knows the basics about ASP.NET development.

Architectural Overview

What’s the Common Scenario? / How does it Usually Work?

The common scenario to reach the desired page on the internet is to write the URL to a browser and press Enter. Basically say the browser asks a server for the requested page. The server builds the page (HTML) and sends the result back to the browser. The browser displays the result to the user and makes HTTP requests to other content like images, etc. Let’s jump back to the stage when the server is building the content of the page. Some parts of the page are usually static data immediately available to use. Another data of the page could be dynamic, either from huge database heavy for calculation or from another server like RSS channel. The point is that some of the data is quickly available and some of the data need time to be loaded. The HTML build by server isn't sending to the browser until it is completely created. That is obvious.

AJAX Comes to the Scene

Using AJAX, you can split the load of the page into multiple phases in a very elegant way. Basically in the first HTTP request, you return the data undemanding to take time to be prepared and then using AJAX you can ask for the rest of the content. Let’s see the sequential diagram.

Pic 1. – Sequential diagram

Pic 1. – Sequential diagram

Depth Look at the AJAX Request in this Case

There are certainly a few questions about the AJAX request in this case. Let’s see some of them:

  • What is the best format of the data returned by the server? XML, JSON, proper HTML or something else?
  • What’s the best type of HTTP endpoint for the AJAX request? Web Service, WCF, ASPX page or something else?
  • Where to do the data binding? On the client or on the server?

The answers to these questions depend on the architecture of your system. You have to choose which implementation will be suitable for you. I chose one concrete implementation which was suitable for my system. It’s the proper HTML as the response of the server and ASPX page as an HTTP end point. The data binding is done by the server, for I'm not providing the data objects to the client.

Concrete Implementation

As I already mentioned, there are several options to implement it. I will describe my implementation now.

HTTP Endpoint

The HTTP endpoint in my solution is responsible for providing all the data in HTML format. The simplest way to achieve this could be using ASPX page or ASHX handler. I chose ASPX page because it’s very simple. The only thing you have to figure out is to remove all the DOM elements automatically generated by Visual Studio. Look at the example now.

<%@ Page Language="C#" AutoEventWireup="true" 
	CodeBehind="LoadData.aspx.cs" Inherits="DnsSelfLoadDiv.LoadData" %>

<asp:repeater runat="server" id="repMain">
        <HeaderTemplate>
            <table>
        </HeaderTemplate>
        <ItemTemplate>
            <tr>
                <td>
                    <%# Eval("Value1") %>
                </td>
                <td>
                    <%# Eval("Value1") %>
                </td>
            </tr>
        </ItemTemplate>
        <FooterTemplate>
            </table>
        </FooterTemplate>
    </asp:repeater>

See, there are the page directives and then directly the repeater. There is no body tag or such a thing. It’s because the result of HTTP endpoint is bound into the existing HTML page.

ASP.NET AJAX Control Responsible for Data Load

Let’s look at the simple diagram describing used files.

Pic 2.

Pic 2.

The control contains two files. It’s the Web Control and the Java Script control. The web control is responsible for creating DIV element into a DOM. The JavaScript class, on the other hand, is far interested because it’s the core of the described functionality. Thanks to Microsoft AJAX JS library the Java Script class can be written as a class and thanks to jQuery the command in the class is very simple to read. So let’s introduce the whole script:

Type.registerNamespace("DotNetSources.SelfLoadDiv");

DotNetSources.SelfLoadDiv = function(element) {
    DotNetSources.SelfLoadDiv.initializeBase(this, [element]);

    // handlers
    this._onLoadHandler = null;
    this._data = false;

    // properties
    this._httpEndPoint = null;
    this._progressImageUrl = null;
}

DotNetSources.SelfLoadDiv.prototype = {

    initialize: function() {
        DotNetSources.SelfLoadDiv.callBaseMethod(this, 'initialize');

        // register handler
        this._onLoadHandler = Function.createDelegate(this, this._get_content);
        Sys.Application.add_load(this._onLoadHandler);

        // hide me fast
        $("#" + this.get_id()).hide();
    },

    _get_content: function() {

        // load progress into myself as another div

        // create div
        var innerDiv = document.createElement("div");
        innerDiv.setAttribute('style', 'text-align: center;');

        // create image
        var pImg = document.createElement("img");
        pImg.setAttribute('src', this.get_progressImageUrl());

        // put image into div
        innerDiv.appendChild(pImg);

        // empty myself
        this.get_element().innerHTML = "";

        // put everything into myself
        this.get_element().appendChild(innerDiv);

        // show me slowly using jQuery
        $("#" + this.get_id()).slideDown("slow", Function.createDelegate
					(this, this._show_progress_step1));

    },

    _show_progress_step1: function() {
        // continue with request

        $.get(this.get_httpEndPoint(), Function.createDelegate
					(this, this._data_available));
    },

    _data_available: function(data) {

        this._data = data;
        // hide myself slowly
        $("#" + this.get_id()).slideUp("slow", Function.createDelegate
					(this, this._data_available_step1));
    },

    _data_available_step1: function() {

        // empty myself
        this.get_element().innerHTML = "";

        // put new content into myself
        this.get_element().innerHTML = this._data;

        // show me slowly
        $("#" + this.get_id()).slideDown("slow");

        // DONE
    },

    //
    // Properties 
    //

    get_httpEndPoint: function() {
        return this._httpEndPoint;
    },

    set_httpEndPoint: function(value) {
        this._httpEndPoint = value;
    },

    get_progressImageUrl: function() {
        return this._progressImageUrl;
    },

    set_progressImageUrl: function(value) {
        this._progressImageUrl = value;
    },

    //
    // Properties 
    //

    dispose: function() {
        //Add custom dispose actions here
        Sys.Application.remove_load(this._onLoadHandler);
        DotNetSources.SelfLoadDiv.callBaseMethod(this, 'dispose');
    }
}
DotNetSources.SelfLoadDiv.registerClass('DotNetSources.SelfLoadDiv', Sys.UI.Control);

I hope there is no need for additional description. Everything begins with the function _get_content and continues with the functions below it. At last, it ends up with the comment //DONE. If you are familiar with jQuery, you can simply change the animations as you like.

Using the Code

To use it, you need to add ScriptManager into your page, register the jQuery library and at last, add the server control. In the server control, you need to specify the progress image URL and the HTTP endpoint from where the data will be loaded. It can look like:

<%@ Register tagPrefix="ex3" namespace="DnsSelfLoadDiv" assembly="DnsSelfLoadDiv" %><asp:ScriptManager runat="server" ID="sManager">
        <Scripts>
            <asp:ScriptReference Path="~/js/jquery-1.3.1.min.js" />
        </Scripts>
    </asp:ScriptManager>
...
<ex3:SimpleSelfloadDiv runat="server" ID="sLoader1" ProgressImageUrl="ajax-loader.gif"
                        HttpEndpoint="LoadData.aspx" />

You can find the whole example in the download package.

Conclusion

Thank you for reading. I'm open for discussion and proposals. Please don't hesitate to write your opinion or vote.

References

History

  • 23. November 2009 - Initial release

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Petr Pechovic
Technical Lead
Czech Republic Czech Republic
Member

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionUsing in a website [modified]membereleazaro18 Nov '11 - 0:21 
Hi, friend. I really like your example. It is great.
 
Now I have a problem. I am trying to use it in an asp.net web site, not web application. So I moved all the coded needed but when I try to add this:
<%@ Register tagPrefix="ex3" namespace="DnsSelfLoadDiv" assembly="DnsSelfLoadDiv" %>
 
I get this error:
Quote:
Parser Error Message: Could not load file or assembly 'DnsSelfLoadDiv' or one of its dependencies. The system cannot find the file specified.

 
I think it is something related with the namespace but after searching on the web, I found that you can't use namespaces unless you are in a web application.
 
Any idea? Thanks.
 
----
 
I moved DnsSelLoadDiv into an ascx file and modified the register enty but I keep getting errors. :(

modified 18 Nov '11 - 7:42.

GeneralVery Nice Article [modified]memberpcphuc24 Mar '10 - 21:43 
I think this is very nice article. You got my 5
Can this technique apply for an aspx page which has some Tabs (div)? The data of first Tab will be available and the data of the rest Tabs will be loaded later.
And there are some buttons on this page to do some works after that. This page also has Master Page.
 
Thanks for your article.
modified on Thursday, March 25, 2010 4:13 AM

GeneralRe: Very Nice ArticlememberPetr Pechovic24 Mar '10 - 22:18 
Thank you very much pcphuc Smile | :) ,
I don’t know if it will work with MasterPage but I would probably recommend not doing this way…. or…. I don’t know, depends on the architecture….
 
Petr
QuestionHow to fire an eventmemberrahulcapquest22 Mar '10 - 5:03 
Hi,
 
I think this i a wonderful article. But there is one thing missing "How can be make server request like button click etc" using this approach.
 
It works very well for putting some static HTML. But as we don’t have Form tag in the aspx page we cannot fire an event.
 
Any ways to make server events?? Frown | :( :(
AnswerRe: How to fire an eventmemberPetr Pechovic22 Mar '10 - 9:33 
Hi rahulcapquest, thanks for dropping by and thanks for nice feedback.
 
Yes, this question seems reasonable to arise when a developer sees this example. In this case, however, the page is just doing some “provider” of data and nothing else.
 
If you need to do some ASP.NET activity inside of the “delay loaded” data then you should consider client side binding as a solution. ASP.NET 4.0 provides a nice way to achieve this. If you are interested, I can point you out to superb article of Dino Esposito which was published recently in the MSDN magazine. The article is here: http://msdn.microsoft.com/en-us/magazine/ee309508.aspx[^] . I think it gives you an excellent overview of how to solve the issue you are facing right now.
 
Petr.
GeneralProblemmemberknocknock8 Mar '10 - 5:22 
Hi There, I tried your solution using ASP.NET User Control ...
but it didn't work,, can u explain that , please ?
 
Best Regards
GeneralProblemmemberknocknock8 Mar '10 - 5:21 
Hi There, I tried your solution using ASP.NET User Control ...
but it didn't work,, can u explain that , please ?
 
BR.
GeneralRe: ProblemmemberPetr Pechovic8 Mar '10 - 6:07 
Hi, yes, I can Smile | :)
 
Petr
GeneralGreat workmemberNazrul23 Feb '10 - 19:56 
Thank you so much for your work
GeneralRe: Great workmemberPetr Pechovic23 Feb '10 - 22:22 
Thanks man Smile | :)
GeneralMuch easier ways to achive thismemberKikoz6823 Feb '10 - 10:16 
No offense, man, but there are much easier ways to do this. Look at Google AdWords at https://adwords.google.com or the Web Scheduler at http://scheduler.codeeffects.com. There are bunch of others, especially online MS Office competitors. Their way is much simpler and requires much less work:
 
1. A server-side page (asp.net, php, coldfusion or whatever you are comfortable with) loads the initial DOM and references to the main script that takes over as soon as the page is finished loading.
2. The script (often called the Gate, or the Port, or the Dashboard or the Snapshot) connects to some end point(s) (soap, wcf, etc) using XmlHTTPRequest (Ajax) and brings back some initial settings that would contain specifics to the current user, initial data, etc. It will also contain a references to the site's functionality, i.e. some array of links similar to site's map. This array is usually used to construct navigation, assign events to nav buttons, etc.
3. Each piece of functionality (or each page) of the site has its own plain html file and a script (Home, Compain, Opportunities, etc. on the AdWords). Every time the user clicks something, the Gate loads the HTML and the script of that functionality from the end point and "injects" them into the DOM. It then gives the control to the loaded script which can do whatever it needs to do, totally independently from the main Gate. If any data exchange is needed between the script and the Gate, a system of custom events is implemented that allows the Gate and scripts to talk to each other.
 
This way you only need to create one server-side page and one port script that would use, say, .NET client library or jQuery to load scripts and HTML. The rest is typical and generally MUCH easier and more reliable, manageable and easier to pick up.
AnswerRe: Much easier ways to achive thismemberPetr Pechovic23 Feb '10 - 12:31 
Hi,
 
Thank you for reading and thank you for a comment.
 
It is a matter of opinion. I still think my way is easier. Basically the WebControl is written. When I want to reach the functionality again, I have to do the following:
 
<ex3:SimpleSelfloadDiv runat="server" ID="sLoader1" ProgressImageUrl="ajax-loader.gif" HttpEndpoint="LoadData.aspx" />
 
Just writing a control declaration and specifying the HTTP endpoint. But as I already mentioned in the article: This implementation doesn’t have to be suitable for everyone. The article is about the “architectural overview” and then it shows you one possible implementation.
 
Maybe you just don’t like the way the control is created (ASP.NET AJAX Control) but that’s another discussion. If you are interested in it, let me point you out to my next article From Simple JavaScript Classes to ASP.NET AJAX Controls[^].
 

Thanks for dropping by, I appreciate it. Petr.
GeneralRe: Much easier ways to achive thismemberKikoz6824 Feb '10 - 3:27 
Hi there Smile | :)
 
Allow me to respectfully disagree. Yes, you NOW just need to declare your control if you need ITS particular functionality on a page. I, on the other side, NOW just need to declare a script's URL in some XML file if I need ANY new functionality on a page. See the difference? Smile | :)
 
If we were to create a brand new "control" project, we would need to do this:
 
1. You need to create the control itself.
2. You either need a separate control for each piece of functionality or you need to "teach" you control how to deal with the entire app.
3. You need to create a data provider ("end point").
4. You need to create the page that would host your control.
5. You need a way to tell your page where to load your functionality from. XML would be fine here.
6. You need to create a page, snippet and/or script every time you need a piece of functionality and "register" it in that XML file so your control could find and load it.
 
The "script injection" approach would be:
 
1. You need to create the "gate" page.
2. You need to create a data provider.
3. You need a way to tell your page where to load your functionality from (XML will work here as well).
4. Every time you need ANY new functionality, you need to create a page and/or script that would be loaded into the "gate" and "register" it in that XML structure. This piece of functionality would be independent from the rest of the app and know on its own what, how and when to do its job.
 
To summarize, the "control" limits us to use particular platform only (.NET in your case) because the implementation of the project would be different on any other platform. The "script injection" allows the use of any platform. Therefore, you need to create and maintain less code and that results in much stable and reliable production.
 
In general, there is a reason why all "big shots" were doing the "injection" for quite some time now and no one would seriously consider any "control" approach. It's similar to why they don't use any "out-of-the-box" libraries such as jQuery. You need a complete freedom if you want to grow. Think about that Wink | ;)
GeneralRe: Much easier ways to achive thismemberPetr Pechovic24 Feb '10 - 6:16 
Hello again Smile | :) ,
 
Well, the solution is in the ASP.NET therefore it depends on the ASP.NET Smile | :) .
 
If you don’t like writing “controls” extended by client capabilities in ASP.NET then you can suggest a better solution here: http://msdn.microsoft.com/en-us/library/bb386450.aspx[^]
 
Thanks, Petr.
GeneralRe: Much easier ways to achive thismemberKikoz6824 Feb '10 - 7:46 
Amen to that Smile | :)
GeneralRe: Much easier ways to achive thismemberPetr Pechovic24 Feb '10 - 10:42 
I do respect your opinion Smile | :) but I still do like the ASP.NET and their ASP.NET AJAX extensions Wink | ;)
GeneralGreat IdeamemberEng. Jalal22 Feb '10 - 23:09 
I liked the idea of incremental loading of the page... nice work ... got my 5
Use your mind for what matters most !
Car Market online

GeneralRe: Great IdeamemberPetr Pechovic23 Feb '10 - 0:18 
Thank you Smile | :)
GeneralRe: Great IdeamemberEng. Jalal23 Feb '10 - 6:27 
I believe it would be perfect to port it to asp.net mvc ... that's where miracles happen. It would be great if you provide an mvc version as well, working with jquery as client side library
 
thanks for the great idea again !
Use your mind for what matters most !
Car Market online

GeneralRe: Great IdeamemberPetr Pechovic23 Feb '10 - 12:44 
Hi,
 
Thanks again Smile | :)
 
Actually it was my intention to do it Smile | :) . I wanted to call it “Web Page Loading in Steps - ASP.NET MVC Solution” Smile | :) but then I realized that it is not enough for an article. Maybe I extend the current article…. I will try…. Thanks for pointing this out Smile | :) . Petr.
GeneralExcelent Work !!!mvpAbhijit Jana16 Feb '10 - 3:20 
This is an excellent article - You already got my 5 for this Big Grin | :-D
GeneralRe: Excelent Work !!!memberPetr Pechovic16 Feb '10 - 7:12 
Thanks a lot Abhijit! Smile | :)
GeneralI had to bookmark this one too!memberMarcelo Ricardo de Oliveira7 Feb '10 - 11:04 
Congratulations, Mr. ASP.NET man, well done! Smile | :)
 
Got 5 from me
cheers,
Marcelo
Take a look at XNA Snooker Club game here in Code Project.

GeneralRe: I had to bookmark this one too!memberPetr Pechovic7 Feb '10 - 21:13 
Smile | :) Thank you Smile | :)
GeneralGreat!memberJorge Bay Gondra20 Jan '10 - 1:57 
Great job!
You have a 5!!!
 
Jorgebg
Press releases
Notas de prensa
Generalgood jobmemberArlen Navasartian14 Jan '10 - 22:44 
5 for me ...
 
-------
Arlen.N

GeneralRe: good jobmemberPetr Pechovic15 Jan '10 - 3:02 
Thank you Arlen. Smile | :)
 

GeneralMy 5 !membercwp423 Jan '10 - 23:07 
Dear Petr,
thanks for that helpful article !
 
You mention above "...best type of HTTP endpoint for the AJAX request? Web Service, WCF, ASPX page..."
Do you know any articles that examine that more deeply ?
 
cwp42

GeneralRe: My 5 ! [modified]memberPetr Pechovic4 Jan '10 - 2:59 
Hi,
 
Thanks for comment.
 
>> Do you know any articles that examine that more deeply ?
 
I can’t recommend any articles on the internet at the moment but the book from Dino, introduced as [2] in the references in the article is completely about this topic. Maybe Dino wrote something similar for MSDN magazine, thus, you can look there. I enjoy to buy books so I bought a book Smile | :)
 
modified on Tuesday, January 5, 2010 11:27 AM

QuestionConflict with App_Themes???membertruongpham14 Dec '09 - 6:49 
Great article. Thanks Petr Pechovic for sharing such a great one.
 
One question raises when I apply Theme for Web project.
First, I create a default theme and add the following into web.config:
 
<pages theme="Theme1">
</pages>
 
If there is not any CSS files to be created, your sample still works just fine.
However, when I create a new CSS file and put it in Theme folder, no matter CSS file has content or not, then self-load never works. That means LoadData.aspx never fires.
 
I have no idea why it happens. Could you please solve it?
 
Thank you,
Henry,
AnswerRe: Conflict with App_Themes???memberPetr Pechovic14 Dec '09 - 9:39 
Hi Henry,
Thank you for comment.
 
It’s weird. It shouldn’t be affected by Themes or CSS. Could you please make an example of such a not working web site, pack it and send it to my e-mail? I will go through the code and let you know what’s wrong as soon as possible. Thanks Petr.
 
My e-mail: http://www.dotnetsources.com/contact.aspx[^]
 

GeneralRe: Conflict with App_Themes???membertruongpham15 Dec '09 - 15:38 
Hi Petr Pechovic,
 
Last night I sleep on this issue for a while and come across the reason why it happens.
I wake up in morning and run over my PC for checking my judgement. Yes, my judgement is true. It turns out that an ASP.NET page cannot work under Themes without runat="server" in <head> tag.
 
In this case, LoadData.aspx doesn't contain runat="server" in <head> tag. So it fails to load this page in SelfLoadDiv.js. It results in loader-icon to stay still forever.
 
Now I put in <head> tag in LoadData.aspx with runat="server". It works just fine with applying Themes.
 
Henry,
GeneralRe: Conflict with App_Themes??? [modified]memberPetr Pechovic16 Dec '09 - 0:15 
Hi Henry,
That is superb Smile | :) . Thank you very much for pointing this out. Thumbs Up | :thumbsup:
 
modified on Wednesday, December 23, 2009 5:26 AM

GeneralNice OnememberAnurag Gandhi30 Nov '09 - 23:27 
Good Approach.
I liked it. Thanks.
 
Anurag Gandhi.
http://www.gandhisoft.com
Life is a computer program and every one is the programmer of his own life.

GeneralRe: Nice OnememberPetr Pechovic1 Dec '09 - 0:28 
Thanks man Smile | :)
 

Generalvery-very useful, thanksmemberEugene Kosevtsov30 Nov '09 - 10:01 
Hi Peter, thank you for such great post! I like idea of Omar's approach to speed up page loading process. And thanks for you - the usability of this approach is becoming easy Smile | :)
I do prefer your idea about the data binding on client side too.
I mean the way where you may use static html page for end point instead of dynamic .aspx. So using static html page as an html markup we can reduce server side overhead (because of full life cycle of aspx takes some server time). So html markup is not taking server time and static url is allowing browser to download the content once and keep it in the cache.
The only thing left is boring about how data for that template will be generated.
 
This is fantastic, thank you many times Smile | :)
 
PS: i love the photos in your picasa, you are really talented creator Smile | :)
GeneralRe: very-very useful, thanksmemberPetr Pechovic30 Nov '09 - 21:46 
Hi Eugene,
 
It's pleasure to read comment like this. The way with static HTML pages is very nice idea. Thanks for it and thanks for comment. It encourages me to write more articles Smile | :)
 
Petr
 
PS: Blush | :O many thanks Smile | :) ... It's always hard for programmers to do something related with the graphics Smile | :)
 

GeneralNice Ariticlememberthiru_thiru23 Nov '09 - 19:40 
It is very nich article to understand..
 
Thank you..
 
Regards,
Thirumurugan g
GeneralRe: Nice AriticlememberPetr Pechovic23 Nov '09 - 21:04 
Glad to hear that. Thank you.
GeneralVery Userfulmembernicholas_pei23 Nov '09 - 16:36 
Hi man,
It's userful and easy to read.   Thank you and thanks Omar.
GeneralRe: Very UserfulmemberPetr Pechovic23 Nov '09 - 21:04 
Thank you Smile | :)

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 23 Nov 2009
Article Copyright 2009 by Petr Pechovic
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid