Omar AL Zabir blog on ASP.NET Ajax and .NET 3.5

Working hard to enrich millions of peoples' lives

Sponsors

News

I am
Co-Founder and CTO of Pageflakes, acquired by LiveUniverse - founded by MySpace founder.

My Public Page
www.pageflakes.com/omar

View Omar AL Zabir's profile on LinkedIn

Read my blog on:

Omar AL Zabir

www.oazabir.com



Views:

Articles

Open source projects

May 2008 - Posts

UFrame: goodness of UpdatePanel and IFRAME combined

UFrame combines the goodness of UpdatePanel and IFRAME in a cross browser and cross platform solution. It allows a DIV to behave like an IFRAME loading content from any page either static or dynamic. It can load pages having both inline and external Javascript and CSS, just like an IFRAME. But unlike IFRAME, it loads the content within the main document and you can put any number of UFrame on your page without slowing down the browser. It supports ASP.NET postback nicely and you can have DataGrid or any other complex ASP.NET control within a UFrame. UFrame works perfectly with ASP.NET MVC making it an replacement for UpdatePanel. Best of all, UFrame is implemented 100% in Javascript making it a cross platform solution. As a result, you can use UFrame on ASP.NET, PHP, JSP or any other platform.

<div class="UFrame" id="UFrame1" src="SomePage.aspx?ID=UFrame1" >
<p>This should get replaced with content from Somepage.aspx</p>
</div>

Response from SomePage.aspx is rendered directly inside the UFrame. Here you see two UFrame's are used to load the same SomePage.aspx as if they are loaded inside IFRAME. Another UFrame is used to load AnotherPage.aspx that shows photos from Flickr.

image

See it in action!

You can test UFrame from:

What is UFrame?

UFrame can load and host a page (ASP.NET, PHP or regular html) inside a DIV. Unlike IFRAME which loads the content inside a browser frame that has no relation with the main document, UFrame loads the content within the same document. Thus all the Javascripts, CSS on the main document flows through the loaded content. It's just like UpdatePanel with IFRAME's src attribute.

The above UFrames are declared like this:

<div id="UFrame1" src="SomePage.aspx" >
<p>This should get replaced with content from Somepage.aspx</p>
</div>

The features of UFrame are:

  • You can build regular ASP.NET/PHP/JSP/HTML page and make them behave as if they are fully AJAX enabled! Simple regular postback will work as if it's an UpdatePanel, or simple hyperlinks will behave as if content is being loaded using AJAX.
  • Load any URL inside a DIV. It can be a PHP, ASP.NET, JSP or regular HTML page.
  • Just like IFRAME, you can set src property of DIVs and they are converted to UFrames when UFrame library loads.
  • Unlike IFRAME, it loads the content within the main document. So, main document's CSS and Javascripts are available to the loaded content.
  • It allows you to build parts of a page as multiple fully independent pages.
  • Each page is built as standalone page. You can build, test and debug each small page independently and put them together on the main page using UFrames.
  • It loads and executes both inline and external scripts from loaded page. You can also render different scripts during UFrame postback.
  • All external scripts are loaded before the body content is set. And all inline scripts are executed when both external scripts and body has been loaded. This way the inline scripts execute when the body content is already available.
  • It loads both inline and external CSS.
  • It handles duplicates nicely. It does not load the same external Javascript or CSS twice.

Download the code

You can download latest version of UFrame along with the VS 2005 and VS 2008 (MVC) example projects from CodePlex:

www.codeplex.com/uframe

Please go to the "Source Code" tab for the latest version. You are invited to join the project and improve it or fix bugs.

Read the article about UFrame

I have published an article about UFrame at CodeProject:

http://www.codeproject.com/KB/aspnet/uframe.aspx

The article explains in details how the UFrame is built. Be prepared for a big dose of Javascript code.

If you find UFrame or the article useful, please vote for me at CodeProject.

kick it on DotNetKicks.com
Fast ASP.NET web page loading by downloading multiple javascripts in batch

A web page can load a lot faster and feel faster if the javascripts on the page can be loaded after the visible content has been loaded and multiple javascripts can be batched into one download. Browsers download one external script at a time and sometimes pause rendering while a script is being downloaded and executed. This makes web pages load and render slow when there are multiple javascripts on the page. For every javascript reference, browser stops downloading and processing of any other content on the page and some browsers (like IE6) pause rendering while it processes the javascript. This gives a slow loading experience and the web page kind of gets 'stuck' frequently. As a result, a web page can only load fast when there are small number of external scripts on the page and the scripts are loaded after the visible content of the page has loaded.

Here's an example, when you visit http://dropthings.omaralzabir.com, you see a lot of Javascripts downloading. Majority of these are from the ASP.NET AJAX framework and the ASP.NET AJAX Control Toolkit project.

Andysnap_003
Figure: Many scripts downloaded on a typical ASP.NET AJAX page having ASP.NET AJAX Control Toolkit

As you see, browser gets stuck for 15 times as it downloads and processes external scripts. This makes page loading "feel" slower. The actual loading time is also pretty bad because these 15 http requests waste 15*100ms = 1500ms on the network latency inside USA. Outside USA, the latency is even higher. Asia gets about 270ms and Australia gets about 380ms latency from any server in USA. So, users outside USA wastes 4 to 6 seconds on network latency where no data is being downloaded. This is an unacceptable performance for any website.

You pay for such high number of script downloads only because you use two extenders from AJAX Control Toolkit and the UpdatePanel of ASP.NET AJAX.

If we can batch the multiple individual script calls into one call like Scripts.ashx as shown in the picture below and download several scripts together in one shot using an HTTP Handler, it saves us a lot of http connection which could be spent doing other valuable work like downloading CSS for the page to show content properly or downloading images on the page that is visible to user.

Andysnap_002
Figure: Download several javascripts over one connection and save call and latency

The Scripts.ashx handler can not only download multiple scripts in one shot, but also has a very short URL form. For example:

/scripts.ashx?initial=a,b,c,d,e&/

Compared to conventional ASP.NET ScriptResource URLs like:

/ScriptResource.axd?d=WzuUYZ-Ggi7-B0tkhjPDTmMmgb5FPLmciWEXQLdjNjt
bmek2jgmm3QETspZjKLvHue5em5kVYJGEuf4kofrcKNL9z6AiMhCe3SrJrcBel_c1
&amp;t=633454272919375000

 

The benefits of downloading multiple Javascript over one http call are:

  • Saves expensive network roundtrip latency where neither browser nor the origin server is doing anything, not even a single byte is being transmitted during the latency
  • Create less "pause" moments for the browser. So, browser can fluently render the content of the page and thus give user a fast loading feel
  • Give browser move time and free http connections to download visible artifacts of the page and thus give user a "something's happening" feel
  • When IIS compression is enabled, the total size of individually compressed files is greater than multiple files compressed after they are combined. This is because each compressed byte stream has compression header in order to decompress the content.
  • This reduces the size of the page html as there are only a few handful of script tag. So, you can easily saves hundreds of bytes from the page html. Especially when ASP.NET AJAX produces gigantic WebResource.axd and ScriptResource.axd URLs that have very large query parameter

The solution is to dynamically parse the response of a page before it is sent to the browser and find out what script references are being sent to the browser. I have built an http module which can parse the generated html of a page and find out what are the script blocks being sent. It then parses those script blocks and find the scripts that can be combined. Then it takes out those individual script tags from the response and adds one script tag that generates the combined response of multiple script tags.

For example, the homepage of Dropthings.com produces the following script tags:

<script type="text/javascript">
...
//]]>
</script>
<script src="/Dropthings/WebResource.axd?d=_w65Lg0FVE-htJvl4_zmXw2&amp;t=633403939286875000"
type="text/javascript"></script>
...
<script src="Widgets/FastFlickrWidget.js" type="text/javascript"></script>
<script src="Widgets/FastRssWidget.js" type="text/javascript"></script>
<script src="/Dropthings/ScriptResource.axd?d=WzuUYZ-Ggi7-B0tkhjPDTmMmgb5FPLmciWEXQLdj
Njtbmek2jgmm3QETspZjKLvHue5em5kVYJGEuf4kofrcKNL9z6AiMhCe3SrJrcBel_c1
&amp;t=633454272919375000"
type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[
...
</script>
<script src="/Dropthings/ScriptResource.axd?d=WzuUYZ-Ggi7-B0tkhjPDTmMmgb5FPLmciWEXQLdjNjtbmek2j
gmm3QETspZjKLvHIbaYWwsewvr_eclXZRGNKzWlaVj44lDEdg9CT2tyH-Yo9jFoQij_XIWxZNETQkZ90
&amp;t=633454272919375000"
type="text/javascript"></script>
<script type="text/javascript">
...
</script>
<script type="text/javascript">
...
</script>
<script type="text/javascript" charset="utf-8">
...
</script>
<script src="Myframework.js" type="text/javascript"></script>
<script type="text/javascript">
...
</script>
<script type="text/javascript">if( typeof Proxy == "undefined" ) Proxy = ProxyAsync;</script>
<script type="text/javascript">
...
</script>
<script src="/Dropthings/ScriptResource.axd?d=WzuUYZ-Ggi7-B0tkhjPDTmMmgb5FPLmciWEXQLdjN
jtbmek2jgmm3QETspZjKLvH-H5JQeA1OWzBaqnbKRQWwc2hxzZ5M8vtSrMhytbB-Oc1
&amp;t=633454272919375000"
type="text/javascript"></script>
<script src="/Dropthings/ScriptResource.axd?d=BXpG1T2rClCdn7QzWc-HrzQ2ECeqBhG6oiVakhRAk
RY6YSaFJsnzqttheoUJJXE4jMUal_1CAxRvbSZ_4_ikAw2
&amp;t=633454540450468750"
type="text/javascript"></script>
<script src="/Dropthings/ScriptResource.axd?d=BXpG1T2rClCdn7QzWc-HrzQ2ECeqBhG6oiVakhRA
kRYRhsy_ZxsfsH4NaPtFtpdDEJ8oZaV5wKE16ikC-hinpw2
&amp;t=633454540450468750"
type="text/javascript"></script>
<script src="/Dropthings/ScriptResource.axd?d=BXpG1T2rClCdn7QzWc-HrzQ2ECeqBhG6oiVakhRAk
RZbimFWogKpiYN4SVreNyf57osSvFc_f24oloxX4RTFfnfj5QsvJGQanl-pbbMbPf01
&amp;t=633454540450468750"
type="text/javascript"></script>
...

<script type="text/javascript">
...
</script>
</body>
</html>

As you see, there are lots of large script tags, in total 15 of them. The solution I will show here will combine the script links and replace with two script links that download 13 of the individual scripts. I have left two scripts out that are related to ASP.NET AJAX Timer extender.

<script type="text/javascript">
...
</script>



<script type="text/javascript" src="Scripts.ashx?initial=a,b,c,d,e,f&/dropthings/"></script>


<script type="text/javascript">
...
</script>

<script type="text/javascript">
...
</script>
<script type="text/javascript">
...
</script>

<script type="text/javascript">
...
</script>

<script type="text/javascript">if( typeof Proxy == "undefined" ) Proxy = ProxyAsync;</script>
<script type="text/javascript">
...
</script>
<script src="/Dropthings/ScriptResource.axd?d=WzuUYZ-..." type="text/javascript"></script>
<script src="/Dropthings/ScriptResource.axd?d=BXpG1T2..." type="text/javascript"></script>

<script type="text/javascript" src="Scripts.ashx?post=C,D,E,F,G,H,I,J&/dropthings/"></script>

<script type="text/javascript">
...
</script>

As you see, 13 of the script links have been combined into two script links. The URL is also smaller than majority of the script references.

There are two steps involved here:

  1. Find out all the script tags being emitted inside generated response HTML and collect them in a buffer. Move them after the visible artifacts in the HTML, especially the <form> tag that contains the generated output of all ASP.NET controls on the page
  2. Parse the buffer and see which script references can be combined into one set. The sets are defined in a configuration file. Replace the individual script references with the combined set reference.

The whole solution is explained in this CodeProject article:

Fast ASP.NET web page loading by downloading multiple javascripts after visible content and in batch
http://www.codeproject.com/KB/aspnet/fastload.aspx

You should be able to use this approach in any ASP.NET (even better if AJAX) application and give your site a big performance boost.

If you like the idea, please vote for me.

Note: The latest source code, with any bug fixes, will be available in the Dropthings source code all the time.

kick it on DotNetKicks.com
More Posts