<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Omar AL Zabir blog on ASP.NET Ajax and .NET 3.5 : javascript</title><link>http://msmvps.com/blogs/omar/archive/tags/javascript/default.aspx</link><description>Tags: javascript</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>I am no more</title><link>http://msmvps.com/blogs/omar/archive/2010/04/25/i-am-no-more.aspx</link><pubDate>Sun, 25 Apr 2010 05:53:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1764207</guid><dc:creator>omar</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;I have moved my blog to&lt;a title="Omar AL Zabir New Blog"&gt; http://omaralzabir.com&lt;/a&gt; and I am no longer blogging here. Please update your readers and subscribe to the feed on the new site.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1764207" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/javascript/default.aspx">javascript</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/C_2300_/default.aspx">C#</category></item><item><title>Fast Streaming Ajax Proxy with GET PUT POST DELETE</title><link>http://msmvps.com/blogs/omar/archive/2010/02/21/fast-streaming-ajax-proxy-with-get-put-post-delete.aspx</link><pubDate>Sun, 21 Feb 2010 18:23:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1758871</guid><dc:creator>omar</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;I have enhanced my streaming Ajax Proxy with POST, PUT and DELETE features. Previously it supported only GET. Now it supports all 4 popular methods for complete REST support. Using this proxy, you can call REST API on external domain directly from your website’s javascript code. You can test the proxy from this link:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://labs.omaralzabir.com/ajaxstreamingproxy/GetPutDeleteTest.aspx"&gt;labs.omaralzabir.com/ajaxstreamingproxy/GetPutDeleteTest.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The latest source code for the Ajax Proxy is available here:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://code.google.com/p/fastajaxproxy/"&gt;http://code.google.com/p/fastajaxproxy/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;You can find a detail CodeProject article that explains how the streaming asynchronous aspect of this proxy works:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.codeproject.com/KB/ajax/ajaxproxy.aspx"&gt;Fast, Scalable, Streaming AJAX Proxy - continuously deliver data from across domains&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Here’s how the test UI looks like where you can test POST, PUT and DELETE:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar.metablogapi/4721.image_5F00_260FD3CF.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="image" border="0" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar.metablogapi/6303.image_5F00_thumb_5F00_10B15CC0.png" width="556" height="484" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;If you want to run the sample source code on your local IIS, make sure you allow the POST, PUT, and DELETE headers on .ashx extension from IIS properties: &lt;/p&gt;  &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar.metablogapi/6303.image_5F00_5F4226C5.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="image" border="0" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar.metablogapi/1172.image_5F00_thumb_5F00_37A7BC69.png" width="644" height="469" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The sample project shows how you can use the proxy to make calls to external domains. You can directly hit any external URL and perform POST or DELETE from your javascript code:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;proxyUrl &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;quot;StreamingProxy.ashx&amp;quot;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;function &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;download&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;method&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;proxyUrl&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;contentUrl&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;isJson&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;bodyContent&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;completeCallback&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;) {
    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;request &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;new &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Sys&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Net&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;WebRequest&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();
    
    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;if &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;method &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;== &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;quot;POST&amp;quot; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;|| &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;method &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;== &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;quot;PUT&amp;quot;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;)
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;request&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;set_httpVerb&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;quot;POST&amp;quot;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);
    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;else
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;request&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;set_httpVerb&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;quot;GET&amp;quot;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);

    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;url &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;proxyUrl &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+ &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;quot;?m=&amp;quot; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+ &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;method &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+ &lt;br /&gt;  (&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;isJson &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;? &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;quot;&amp;amp;t=&amp;quot; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+ &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;escape&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;quot;application/json&amp;quot;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;) : &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;) + &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;quot;&amp;amp;u=&amp;quot; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+ &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;escape&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;contentUrl&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);

    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;request&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;set_url&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;url&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);

    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;if &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;bodyContent&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;length &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;&amp;gt; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#8acccf;"&gt;0&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;) {
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;request&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;set_body&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;bodyContent&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;request&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;get_headers&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;()[&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;quot;Content-Length&amp;quot;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;] = &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;bodyContent&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;length&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
    }

    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;startTime &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;new &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Date&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;().&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;getTime&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();

    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;request&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;add_completed&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;function&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;executor&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;) {
        &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;if &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;executor&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;get_responseAvailable&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;()) {
            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;content &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;executor&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;get_responseData&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();
            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;endTime &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;new &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Date&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;().&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;getTime&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();

            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;statistics &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;=
            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;quot;Duration: &amp;quot; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+ (&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;endTime &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;- &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;startTime&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;) + &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;quot;ms&amp;quot; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+ &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;#39;\n&amp;#39; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+
            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;quot;Length: &amp;quot; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+ &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;content&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;length &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+ &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;quot; bytes&amp;quot; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+ &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;#39;\n&amp;#39; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+
            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;quot;Status Code: &amp;quot; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+ &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;executor&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;get_statusCode&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;() + &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;quot; &amp;quot; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+ &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;#39;\n&amp;#39; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+
            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;quot;Status: [&amp;quot; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+ &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;executor&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;get_statusText&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;() + &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;quot;]&amp;quot; &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;+ &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;appendStat&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;statistics&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);

            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;$get&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#c89191;"&gt;&amp;#39;resultContent&amp;#39;&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;).&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;value &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;content&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;;
            &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;completeCallback&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();
        }
    });

    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;var &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;executor &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#eaeaac;"&gt;new &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Sys&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;Net&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;XMLHttpExecutor&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();
    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;request&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;set_executor&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;executor&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;);
    &lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;executor&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dfdfbf;"&gt;executeRequest&lt;/span&gt;&lt;span style="background:#3f3f3f;color:#dcdccc;"&gt;();
}
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;I am using MS AJAX here. You can use jQuery to perform the same test as well. All you need to do is hit the URL of the StreamingProxy.ashx and pass the actual URL in query string parameter “u” and pass the type of the http method in query string parameter “m”. That’s it!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1758871" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/javascript/default.aspx">javascript</category><category domain="http://msmvps.com/blogs/omar/archive/tags/ajax/default.aspx">ajax</category></item><item><title>7 tips for for loading Javascript rich Web 2.0-like sites significantly faster</title><link>http://msmvps.com/blogs/omar/archive/2009/09/25/7-tips-for-for-loading-javascript-rich-web-2-0-like-sites-significantly-faster.aspx</link><pubDate>Fri, 25 Sep 2009 14:46:19 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1726818</guid><dc:creator>omar</dc:creator><slash:comments>11</slash:comments><description>&lt;h2&gt;Introduction&lt;/h2&gt;  &lt;p&gt;When you create rich Ajax application, you use external JavaScript frameworks and you have your own homemade code that drives your application. The problem with well known JavaScript framework is, they offer rich set of features which are not always necessary in its entirety. You may end up using only 30% of jQuery but you still download the full jQuery framework. So, you are downloading 70% unnecessary scripts. Similarly, you might have written your own javascripts which are not always used. There might be features which are &lt;strong&gt;not&lt;/strong&gt; used when the site loads for the first time, resulting in unnecessary download during initial load. Initial loading time is crucial – it can make or break your website. We did some analysis and found that every 500ms we added to initial loading, we lost approx 30% traffic who never wait for the whole page to load and just close browser or go away. So, saving initial loading time, even by couple of hundred milliseconds, is crucial for survival of a startup, especially if it’s a Rich AJAX website.&lt;/p&gt;  &lt;p&gt;You must have noticed Microsoft’s new tool &lt;a title="Doloto download optimizer" href="http://research.microsoft.com/en-us/projects/doloto/"&gt;Doloto&lt;/a&gt; which helps solve the following problem:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Modern Web 2.0 applications, such as GMail, Live Maps, Facebook and many others, use a combination of Dynamic HTML, JavaScript and other Web browser technologies commonly referred as AJAX to push page generation and content manipulation to the client web browser. This improves the responsiveness of these network-bound applications, but the shift of application execution from a back-end server to the client also often dramatically increases the amount of code that must first be downloaded to the browser. This creates an unfortunate Catch-22: to create responsive distributed Web 2.0 applications developers move code to the client, but for an application to be responsive, the code must first be transferred there, which takes time.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Microsoft Research looked at this problem and published &lt;a title="Doloto Research Papper" href="http://research.microsoft.com/en-us/projects/doloto/fse08.pdf"&gt;this research paper in 2008&lt;/a&gt;, where they showed how much improvement can be achieved on initial loading if there was a way to split the javascripts frameworks into two parts – one primary part which is absolutely essential for initial rendering of the page and one auxiliary part which is not essential for initial load and can be downloaded later or on-demand when user does some action. They looked at my earlier startup &lt;a title="Web 2.0 Start Page" href="http://www.pageflakes.com"&gt;Pageflakes&lt;/a&gt; and reported:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;2.2.2 Dynamic Loading: Pageflakes      &lt;br /&gt;A contrast to Bunny Hunt is the &lt;a title="Pageflakes Web 2.0 start page" href="http://www.pageflakes.com"&gt;Pageflakes&lt;/a&gt; application, an       &lt;br /&gt;industrial-strength mashup page providing portal-like functionality.       &lt;br /&gt;While the download size for Pageflakes is over 1 MB, its initial       &lt;br /&gt;execution time appears to be quite fast. Examining network activity       &lt;br /&gt;reveals that Pageflakes downloads only a small stub of code       &lt;br /&gt;with the initial page, and loads the rest of its code dynamically in       &lt;br /&gt;the background. As illustrated by Pageflakes, developers today can       &lt;br /&gt;use dynamic code loading to improve their web application’s performance.       &lt;br /&gt;However, designing an application architecture that is       &lt;br /&gt;amenable to dynamic code loading requires careful consideration       &lt;br /&gt;of JavaScript language issues such as function closures, scoping,       &lt;br /&gt;etc. Moreover, an optimal decomposition of code into dynamically       &lt;br /&gt;loaded components often requires developers to set aside the semantic       &lt;br /&gt;groupings of code and instead primarily consider the execution       &lt;br /&gt;order of functions. Of course, evolving code and changing       &lt;br /&gt;user workloads make both of these issues a software maintenance       &lt;br /&gt;nightmare.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Back in 2007, I was looking at ways to improve the initial load time and reduce user dropout. The number of users who would not wait for the page to load and go away was growing day by day as we introduced new and cool features. It was a surprise. We thought new features will keep more users on our site but the opposite happened. Analysis concluded it was the initial loading time that caused more dropout than it retained users. So, all our hard work was essentially going to drain and we had to come up with something ground breaking to solve the problem. Of course we had already tried all the basic stuffs – &lt;a title="IIS 6 compression setup quick and easy way" href="http://msmvps.com/blogs/omar/archive/2006/08/10/iis-6-compression-quickest-and-effective-way-to-do-it-for-asp-net-compression.aspx"&gt;IIS compression&lt;/a&gt;, &lt;a title="Making best use of cache for faster page loading" href="http://msmvps.com/blogs/omar/archive/2006/08/10/iis-6-compression-quickest-and-effective-way-to-do-it-for-asp-net-compression.aspx"&gt;browser caching&lt;/a&gt;, &lt;a title="Ensure - loading javascript, css, html on demand" href="http://www.codeplex.com/ensure"&gt;on-demand loading of JavaScript, css and html&lt;/a&gt; when user does something, &lt;a title="Deferred Javascript Execution" href="http://ajaxian.com/archives/gmail-mobile-latency"&gt;deferred JavaScript execution&lt;/a&gt; – but nothing helped. The frameworks and our own hand coded framework was just too large. So, the idea tricked me, what if we could load functions inside a class in two steps. First step will load the class with absolutely essential functions and second step will inject more functions to the existing classes.&lt;/p&gt;  &lt;p&gt;I published a codeproject article which shows you 7 tricks to significantly improve page load time even if you have large amount of Javascript used on the page.&lt;/p&gt;  &lt;p&gt;&lt;a title="7 Tips for Loading JavaScript Rich Web 2.0-like Sites Significantly Faster" href="http://www.codeproject.com/KB/ajax/fastjavascript.aspx"&gt;7 Tips for Loading JavaScript Rich Web 2.0-like Sites Significantly Faster&lt;/a&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Use Doloto &lt;/li&gt;    &lt;li&gt;Split a Class into Multiple JavaScript Files &lt;/li&gt;    &lt;li&gt;Stub the Functions Which Aren&amp;#39;t Called During Initial Load &lt;/li&gt;    &lt;li&gt;JavaScript Code in Text &lt;/li&gt;    &lt;li&gt;Break UI Loading into Multiple Stages &lt;/li&gt;    &lt;li&gt;Always Grow Content from Top to Bottom, Never Shrink or Jump &lt;/li&gt;    &lt;li&gt;Deliver Browser Specific Script from Server &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;If you like these tricks, please vote for me!&lt;/p&gt;&lt;div class="wlWriterHeaderFooter" style="margin:0px;padding:0px 0px 0px 0px;"&gt;&lt;a href="http://dotnetburner.com/vote?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2009%2f09%2f25%2f7-tips-for-for-loading-javascript-rich-web-2-0-like-sites-significantly-faster.aspx" rev="vote-for"&gt;&lt;img src="http://dotnetburner.com/image.axd?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2009%2f09%2f25%2f7-tips-for-for-loading-javascript-rich-web-2-0-like-sites-significantly-faster.aspx" style="border:0px;" alt="Burn!" /&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2009%2f09%2f25%2f7-tips-for-for-loading-javascript-rich-web-2-0-like-sites-significantly-faster.aspx" rev="vote-for"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2009%2f09%2f25%2f7-tips-for-for-loading-javascript-rich-web-2-0-like-sites-significantly-faster.aspx" style="border:0px;" alt="kick it" /&gt;&lt;/a&gt;&amp;nbsp;&lt;a rev="vote-for" href="http://dotnetshoutout.com/Submit?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2009%2f09%2f25%2f7-tips-for-for-loading-javascript-rich-web-2-0-like-sites-significantly-faster.aspx"&gt;&lt;img alt="Shout it" src="http://dotnetshoutout.com/image.axd?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2009%2f09%2f25%2f7-tips-for-for-loading-javascript-rich-web-2-0-like-sites-significantly-faster.aspx" style="border:0px;" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1726818" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/performance/default.aspx">performance</category><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/javascript/default.aspx">javascript</category><category domain="http://msmvps.com/blogs/omar/archive/tags/ajax/default.aspx">ajax</category><category domain="http://msmvps.com/blogs/omar/archive/tags/optimize/default.aspx">optimize</category></item><item><title>Web 2.0 AJAX Portal using jQuery, ASP.NET 3.5, Silverlight, Linq to SQL, WF and Unity</title><link>http://msmvps.com/blogs/omar/archive/2009/04/08/web-2-0-ajax-portal-using-jquery-asp-net-3-5-silverlight-linq-to-sql-wf-and-unity.aspx</link><pubDate>Wed, 08 Apr 2009 18:16:22 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1685991</guid><dc:creator>omar</dc:creator><slash:comments>12</slash:comments><description>&lt;p&gt;&lt;a title="Dropthings Web 2.0 style AJAX portal" href="http://dropthings.omaralzabir.com" target="_blank"&gt;Dropthings&lt;/a&gt; – my &lt;a title="Dropthings - Open Source AJAX Portal" href="http://www.codeplex.com/dropthings" target="_blank"&gt;open source&lt;/a&gt; Web 2.0 Ajax Portal has gone through a technology overhauling. Previously it was built using ASP.NET AJAX, a little bit of Workflow Foundation and Linq to SQL. Now Dropthings boasts full &lt;strong&gt;jQuery&lt;/strong&gt; front-end combined with ASP.NET AJAX &lt;code&gt;UpdatePanel&lt;/code&gt;, &lt;strong&gt;Silverlight widget&lt;/strong&gt;, full &lt;strong&gt;Workflow Foundation&lt;/strong&gt; implementation on the business layer, 100% &lt;strong&gt;Linq to SQL Compiled Queries&lt;/strong&gt; on the data access layer, Dependency Injection and Inversion of Control (IoC) using &lt;strong&gt;Microsoft Enterprise Library 4.1&lt;/strong&gt; and &lt;strong&gt;Unity&lt;/strong&gt;. It also has a ASP.NET AJAX Web Test framework that makes it real easy to write Web Tests that simulates real user actions on AJAX web pages. This article will walk you through the challenges in getting these new technologies to work in an ASP.NET website and how performance, scalability, extensibility and maintainability has significantly improved by the new technologies. Dropthings has been licensed for commercial use by prominent companies including BT Business, Intel, Microsoft IS, Denmark Government portal for Citizens; Startups like Limead and many more. So, this is serious stuff! There’s a very cool open source implementation of Dropthings framework available at &lt;a title="AJAX Portal at National University of Singapore" href="http://nexus.nus.edu.sg/apicta" target="_blank"&gt;National University of Singapore&lt;/a&gt; portal.&lt;/p&gt;  &lt;p&gt;Visit: &lt;a href="http://dropthings.omaralzabir.com"&gt;http://dropthings.omaralzabir.com&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_57907290.png"&gt;&lt;img title="Dropthings AJAX Portal" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="529" alt="Dropthings AJAX Portal" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_37551A39.png" width="600" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I have published a new article on this on CodeProject:&lt;/p&gt;  &lt;p&gt;&lt;a title="Web 2.0 AJAX Portal using jQuery, ASP.NET 3.5, Silverlight, Linq to SQL, WF and Unity" href="http://www.codeproject.com/KB/ajax/Web20Portal.aspx"&gt;http://www.codeproject.com/KB/ajax/Web20Portal.aspx&lt;/a&gt;&lt;/p&gt;  &lt;h2&gt;Get the source code&lt;/h2&gt;  &lt;p&gt;Latest source code is hosted at Google code:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://code.google.com/p/dropthings"&gt;http://code.google.com/p/dropthings&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;There’s a CodePlex site for documentation and issue tracking:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.codeplex.com/dropthings"&gt;http://www.codeplex.com/dropthings&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;You will need Visual Studio 2008 Team Suite with Service Pack 1 and Silverlight 2 SDK in order to run all the projects. If you have only Visual Studio 2008 Professional, then you will have to remove the Dropthings.Test project.&lt;/p&gt;  &lt;h2&gt;New features introduced&lt;/h2&gt;  &lt;p&gt;Dropthings new release has the following features:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Template users – you can define a user who’s pages and widgets are used as a template for new users. Whatever you put in that template user’s pages, it will be copied for every new user. Thus this is an easier way to define the default pages and widgets for new users. Similarly you can do the same for a registered user. The template users can be defined in the &lt;code&gt;web.config&lt;/code&gt;. &lt;/li&gt;    &lt;li&gt;Widget-to-Widget communication – Widgets can send message to each other. Widgets can subscribe to an Event Broker and exchange messages using a Pub-Sub pattern. &lt;/li&gt;    &lt;li&gt;WidgetZone – you can create any number of zones in any shape on the page. You can have widgets laid in horizontal layout, you can have zones on different places on the page and so on. With this zone model, you are no longer limited to the Page-Column model where you could only have N vertical columns. &lt;/li&gt;    &lt;li&gt;Role based widgets – now widgets are mapped to roles so that you can allow different users to see different widget list using &lt;code&gt;ManageWidgetPersmission.aspx.&lt;/code&gt; &lt;/li&gt;    &lt;li&gt;Role based page setup – you can define page setup for different roles. For ex, Managers see different pages and widgets than Employees. &lt;/li&gt;    &lt;li&gt;Widget maximize – you can maximize a widget to take full screen. Handy for widgets with lots of content. &lt;/li&gt;    &lt;li&gt;Free form resize – you can freely resize widgets vertically. &lt;/li&gt;    &lt;li&gt;Silverlight Widgets – You can now make widgets in Silverlight! &lt;/li&gt; &lt;/ul&gt;  &lt;h2&gt;Why the technology overhauling&lt;/h2&gt;  &lt;p&gt;Performance, Scalability, Maintainability and Extensibility – four key reasons for the overhauling. Each new technology solved one of more of these problems. &lt;/p&gt;  &lt;p&gt;First, jQuery was used to replace my personal hand-coded large amount of Javascript code that offered the client side drag &amp;amp; drop and other UI effects. jQuery already has a rich set of library for Drag &amp;amp; Drop, Animations, Event handling, cross browser javascript framework and so on. So, using jQuery means opening the door to thousands of jQuery plugins to be offered on Dropthings. This made Dropthings highly extensible on the client side. Moreover, jQuery is very light. Unlike AJAX Control Toolkit jumbo sized framework and heavy control extenders, jQuery is very lean. So, total javascript size decreased significantly resulting in improved page load time. In total, the jQuery framework, AJAX basic framework, all my stuffs are total 395KB, sweet! Performance is key; it makes or breaks a product.&lt;/p&gt;  &lt;p&gt;Secondly, Linq to SQL queries are replaced with Compiled Queries. Dropthings did not survive a load test when regular lambda expressions were used to query database. I could only reach up to 12 Req/Sec using 20 concurrent users without burning up web server CPU on a Quad Core DELL server. &lt;/p&gt;  &lt;p&gt;Thirdly, Workflow Foundation is used to build operations that require multiple Data Access Classes to perform together in a single transaction. Instead of writing large functions with many if…else conditions, for…loops, it’s better to write them in a Workflow because you can visually see the flow of execution and you can reuse Activities among different Workflows. Best of all, architects can design workflows and developers can fill-in code inside Activities. So, I could design a complex operations in a workflow without writing the real code inside Activities and then ask someone else to implement each Activity. It is like handing over a design document to developers to implement each unit module, only that here everything is strongly typed and verified by compiler. If you strictly follow Single Responsibility Principle for your Activities, which is a smart way of saying one Activity does only one and very simple task, you end up with a highly reusable and maintainable business layer and a very clean code that’s easily extensible.&lt;/p&gt;  &lt;p&gt;Fourthly, &lt;a title="Unity Dependency Injection framework" href="http://www.codeplex.com/unity" target="_blank"&gt;Unity&lt;/a&gt; Dependency Injection (DI) framework is used to pave the path for unit testing and dependency injection. It offers Inversion of Control (IoC), which enables testing individual classes in isolation. Moreover, it has a handy feature to control lifetime of objects. Instead of creating instance of commonly used classes several times within the same request, you can make instances thread level, which means only one instance is created per thread and subsequent calls reuse the same instance. Are these going over your head? No worries, continue reading, I will explain later on.&lt;/p&gt;  &lt;p&gt;Fifthly, enabling API for Silverlight widgets allows more interactive widgets to be built using Silverlight. HTML and Javascripts still have limitations on smooth graphics and continuous transmission of data from web server. Silverlight solves all of these problems.&lt;/p&gt;  &lt;p&gt;Read the article for details on how all these improvements were done and how all these hot techs play together in a very useful open source project for enterprises.&lt;/p&gt;  &lt;p&gt;&lt;a title="Web 2.0 AJAX Portal using jQuery, ASP.NET 3.5, Silverlight, Linq to SQL, WF and Unity" href="http://www.codeproject.com/KB/ajax/Web20Portal.aspx"&gt;http://www.codeproject.com/KB/ajax/Web20Portal.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Don’t forget to vote for me if you like it.&lt;/p&gt;&lt;div class="wlWriterHeaderFooter" style="text-align:left;margin:0px;padding:4px 4px 4px 4px;"&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http://msmvps.com/blogs/omar/archive/2009/04/08/web-2-0-ajax-portal-using-jquery-asp-net-3-5-silverlight-linq-to-sql-wf-and-unity.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://msmvps.com/blogs/omar/archive/2009/04/08/web-2-0-ajax-portal-using-jquery-asp-net-3-5-silverlight-linq-to-sql-wf-and-unity.aspx&amp;amp;bgcolor=0080C0&amp;amp;fgcolor=FFFFFF&amp;amp;border=000000&amp;amp;cbgcolor=808080&amp;amp;cfgcolor=000000" alt="DotNetKicks Image" border="0/" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1685991" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/linq/default.aspx">linq</category><category domain="http://msmvps.com/blogs/omar/archive/tags/workflow/default.aspx">workflow</category><category domain="http://msmvps.com/blogs/omar/archive/tags/javascript/default.aspx">javascript</category><category domain="http://msmvps.com/blogs/omar/archive/tags/ajax/default.aspx">ajax</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/silverlight/default.aspx">silverlight</category></item><item><title>ensure - Ensure relevant Javascript and HTML are loaded before using them</title><link>http://msmvps.com/blogs/omar/archive/2008/06/09/ensure-ensure-relevant-javascript-and-html-are-loaded-before-using-them.aspx</link><pubDate>Mon, 09 Jun 2008 06:08:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1633238</guid><dc:creator>omar</dc:creator><slash:comments>1</slash:comments><description>&lt;p&gt;&lt;code&gt;ensure&lt;/code&gt; allows you to load Javascript, HTML and CSS on-demand, whenever they are needed. It saves you from writing a gigantic Javascript framework up front so that you can ensure all functions are available whenever they are needed. It also saves you from delivering all possible html on your default page (e.g. default.aspx) hoping that they might some day be needed on some user action. Delivering Javascript, html fragments, CSS during initial loading that is not immediately used on first view makes initial loading slow. Moreover, browser operations get slower as there are lots of stuff on the browser DOM to deal with. So, &lt;code&gt;ensure&lt;/code&gt; saves you from delivering unnecessary javascript, html and CSS up front, instead load them on-demand. Javascripts, html and CSS loaded by &lt;code&gt;ensure&lt;/code&gt; remain in the browser and next time when &lt;code&gt;ensure&lt;/code&gt; is called with the same Javascript, CSS or HTML, it does not reload them and thus saves from repeated downloads.  &lt;/p&gt;
&lt;p&gt;Ensure supports &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt;, &lt;a href="http://www.asp.net/ajax"&gt;Microsoft ASP.NET AJAX&lt;/a&gt; and &lt;a href="http://www.prototypejs.org/"&gt;Prototype &lt;/a&gt;framework. This means you can use it on any html, ASP.NET, PHP, JSP page that uses any of the above framework.  &lt;/p&gt;
&lt;p&gt;For example, you can use &lt;code&gt;ensure&lt;/code&gt; to download Javascript on demand:  &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class="jscript"&gt;ensure( { js: &amp;quot;Some.js&amp;quot; }, function()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SomeJS(); // The function SomeJS is available in Some.js only&lt;br /&gt;});&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The above code ensures Some.js is available before executing the code. If the SomeJS.js has already been loaded, it executes the function write away. Otherwise it downloads Some.js, waits until it is properly loaded and only then it executes the function. Thus it saves you from deliverying Some.js upfront when you only need it upon some user action.  &lt;/p&gt;
&lt;p&gt;Similarly you can wait for some HTML fragment to be available, say a popup dialog box. There&amp;#39;s no need for you to deliver HTML for all possible popup boxes that you will ever show to user on your default web page. You can fetch the HTML whenever you need them.  &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class="jscript"&gt;ensure( {html: &amp;quot;Popup.html&amp;quot;}, function()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // The element &amp;quot;Popup&amp;quot; is available only in Popup.html&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; document.getElementById(&amp;quot;Popup&amp;quot;).style.display = &amp;quot;&amp;quot;;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;});&lt;/pre&gt;
&lt;p&gt;The above code downloads the html from &amp;quot;Popup.html&amp;quot; and adds it into the body of the document and then fires the function. So, you code can safely use the UI element from that html.  &lt;/p&gt;
&lt;p&gt;You can mix match Javascript, html and CSS altogether in one &lt;code&gt;ensure&lt;/code&gt; call. For example,  &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class="jscript"&gt;ensure( { js: &amp;quot;popup.js&amp;quot;, html: &amp;quot;popup.html&amp;quot;, css: &amp;quot;popup.css&amp;quot; }, function()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PopupManager.show();&lt;br /&gt;});&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;You can also specify multiple Javascripts, html or CSS files to ensure all of them are made available before executing the code:  &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class="jscript"&gt;ensure( { js: [&amp;quot;blockUI.js&amp;quot;,&amp;quot;popup.js&amp;quot;], html: [&amp;quot;popup.html&amp;quot;, &amp;quot;blockUI.html&amp;quot;], css: [&amp;quot;blockUI.css&amp;quot;, &amp;quot;popup.css&amp;quot;] }, function()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; BlockUI.show();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PopupManager.show();&lt;br /&gt;});&lt;/pre&gt;
&lt;p&gt;You might think you are going to end up writing a lot of &lt;code&gt;ensure&lt;/code&gt; code all over your Javascript code and result in a larger Javascript file than before. In order to save you javascript size, you can define shorthands for commonly used files:  &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class="jscript"&gt;var JQUERY = { js: &amp;quot;jquery.js&amp;quot; };&lt;br /&gt;var POPUP = { js: [&amp;quot;blockUI.js&amp;quot;,&amp;quot;popup.js&amp;quot;], html: [&amp;quot;popup.html&amp;quot;, &amp;quot;blockUI.html&amp;quot;], css: [&amp;quot;blockUI.css&amp;quot;, &amp;quot;popup.css&amp;quot;] };&lt;br /&gt;...&lt;br /&gt;...&lt;br /&gt;ensure( JQUERY, POPUP, function() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $(&amp;quot;DeleteConfirmPopupDIV&amp;quot;).show();&lt;br /&gt;});&lt;br /&gt;...&lt;br /&gt;...&lt;br /&gt;ensure( POPUP, function()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $(&amp;quot;SaveConfirmationDIV&amp;quot;).show();&lt;br /&gt;);&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;While loading html, you can specify a container element where ensure can inject the loaded HTML. For example, you can say load HtmlSnippet.html and then inject the content inside a DIV named &amp;quot;exampleDiv&amp;quot;  &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class="jscript"&gt;ensure( { html: [&amp;quot;popup.html&amp;quot;, &amp;quot;blockUI.html&amp;quot;], parent: &amp;quot;exampleDiv&amp;quot;}, function(){});&lt;/pre&gt;
&lt;p&gt;You can also specify Javascript and CSS that will be loaded along with the html.&amp;nbsp; &lt;/p&gt;
&lt;h3&gt;How ensure works&lt;/h3&gt;
&lt;p&gt;The following CodeProject article explains in detail how ensure it built. Be prepared for a high dose of Javascript techniques:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.codeproject.com/KB/ajax/ensure.aspx"&gt;http://www.codeproject.com/KB/ajax/ensure.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you find ensure useful, please vote for me. &lt;/p&gt;
&lt;h3&gt;Download Code&lt;/h3&gt;
&lt;p&gt;Download latest source code from CodePlex: &lt;a href="http://www.codeplex.com/ensure"&gt;www.codeplex.com/ensure&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class="sbmLink"&gt; 
&lt;table cellpadding="1" cellspacing="1"&gt;

&lt;tr&gt;
&lt;td class="sbmText"&gt;Share this post : &lt;/td&gt;
&lt;td class="sbmDim"&gt;&lt;a target="_blank" href="http://del.icio.us/post?url=http://www.codeproject.com/KB/ajax/ensure.aspx&amp;amp;;title=Ensure" title="Post it to del.icio.us" class="sbmDim"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" alt="" /&gt;&lt;/a&gt;  &lt;/td&gt;
&lt;td class="sbmDim"&gt;&lt;a target="_blank" href="http://digg.com/submit?phase=2&amp;amp;url=http://www.codeproject.com/KB/ajax/ensure.aspx&amp;amp;title=Ensure" title="Post it to digg" class="sbmDim"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" alt="" /&gt;&lt;/a&gt;  &lt;/td&gt;
&lt;td class="sbmDim"&gt;&lt;a target="_blank" href="http://www.dotnetkicks.com/kick/?url=http://www.codeproject.com/KB/ajax/ensure.aspx&amp;amp;title=Ensure" title="Post it to dotnetkicks" class="sbmDim"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" alt="" /&gt;&lt;/a&gt;  &lt;/td&gt;
&lt;td class="sbmDim"&gt;&lt;a target="_blank" href="http://www.furl.net/store?s=f&amp;amp;to=0&amp;amp;u=http://www.codeproject.com/KB/ajax/ensure.aspx&amp;amp;ti=Ensure" title="Post it to furl" class="sbmDim"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/furl4.png" alt="" /&gt;&lt;/a&gt;  &lt;/td&gt;
&lt;td class="sbmDim"&gt;&lt;a target="_blank" href="https://favorites.live.com/quickadd.aspx?marklet=1&amp;amp;mkt=en-us&amp;amp;url=http://www.codeproject.com/KB/ajax/ensure.aspx&amp;amp;title=Ensure" title="Post it to live" class="sbmDim"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/live4.png" alt="" /&gt;&lt;/a&gt;  &lt;/td&gt;
&lt;td class="sbmDim"&gt;&lt;a target="_blank" href="http://reddit.com/submit?url=http://www.codeproject.com/KB/ajax/ensure.aspx&amp;amp;title=Ensure" title="Post it to reddit!" class="sbmDim"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" alt="" /&gt;&lt;/a&gt;  &lt;/td&gt;
&lt;td class="sbmDim"&gt;&lt;a target="_blank" href="http://www.spurl.net/spurl.php?v=3&amp;amp;url=http://www.codeproject.com/KB/ajax/ensure.aspx&amp;amp;title=Ensure" title="Post it to spurl" class="sbmDim"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/spurl8.png" alt="" /&gt;&lt;/a&gt;  &lt;/td&gt;
&lt;td class="sbmDim"&gt;&lt;a target="_blank" href="http://technorati.com/faves/?add=http://www.codeproject.com/KB/ajax/ensure.aspx&amp;amp;title=Ensure" title="Post it to technorati!" class="sbmDim"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" alt="" /&gt;&lt;/a&gt;  &lt;/td&gt;
&lt;td class="sbmDim"&gt;&lt;a target="_blank" href="http://myweb.yahoo.com/myresults/bookmarklet?u=http://www.codeproject.com/KB/ajax/ensure.aspx&amp;amp;t=Ensure" title="Post it to yahoo!" class="sbmDim"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/yahoo9.png" alt="" /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
&lt;/span&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.codeproject.com%2fKB%2fajax%2fensure.aspx"&gt;&lt;img border="0" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.codeproject.com%2fKB%2fajax%2fensure.aspx" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1633238" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/performance/default.aspx">performance</category><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/javascript/default.aspx">javascript</category><category domain="http://msmvps.com/blogs/omar/archive/tags/ajax/default.aspx">ajax</category></item><item><title>UFrame: goodness of UpdatePanel and IFRAME combined</title><link>http://msmvps.com/blogs/omar/archive/2008/05/24/uframe-goodness-of-updatepanel-and-iframe-combined.aspx</link><pubDate>Sat, 24 May 2008 19:31:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1626915</guid><dc:creator>omar</dc:creator><slash:comments>50</slash:comments><description>&lt;p&gt;&lt;span style="text-decoration:underline;"&gt;UFrame&lt;/span&gt; combines the goodness of &lt;span style="text-decoration:underline;"&gt;UpdatePanel&lt;/span&gt; and &lt;span style="text-decoration:underline;"&gt;IFRAME&lt;/span&gt; in a cross browser and cross platform solution. It allows a &lt;span style="text-decoration:underline;"&gt;DIV&lt;/span&gt; to behave like an &lt;span style="text-decoration:underline;"&gt;IFRAME&lt;/span&gt; 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 &lt;span style="text-decoration:underline;"&gt;UFrame&lt;/span&gt; on your page without slowing down the browser. It supports ASP.NET postback nicely and you can have &lt;span style="text-decoration:underline;"&gt;DataGrid&lt;/span&gt; or any other complex ASP.NET control within a &lt;span style="text-decoration:underline;"&gt;UFrame&lt;/span&gt;. &lt;span style="text-decoration:underline;"&gt;UFrame&lt;/span&gt; works perfectly with &lt;strong&gt;ASP.NET MVC&lt;/strong&gt; making it an replacement for &lt;span style="text-decoration:underline;"&gt;UpdatePanel&lt;/span&gt;. Best of all, &lt;span style="text-decoration:underline;"&gt;UFrame&lt;/span&gt; is implemented 100% in Javascript making it a cross platform solution. As a result, you can use &lt;span style="text-decoration:underline;"&gt;UFrame&lt;/span&gt; on &lt;strong&gt;ASP.NET, PHP, JSP&lt;/strong&gt; or any other platform. &lt;/p&gt;
&lt;div&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;UFrame&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;UFrame1&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;src&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;SomePage.aspx?ID=UFrame1&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;p&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;This should get replaced with content from Somepage.aspx&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;p&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Response from &lt;span style="text-decoration:underline;"&gt;SomePage.aspx&lt;/span&gt; is rendered directly inside the &lt;span style="text-decoration:underline;"&gt;UFrame&lt;/span&gt;. Here you see two &lt;span style="text-decoration:underline;"&gt;UFrame&lt;/span&gt;&amp;#39;s are used to load the same &lt;span style="text-decoration:underline;"&gt;SomePage.aspx&lt;/span&gt; as if they are loaded inside &lt;span style="text-decoration:underline;"&gt;IFRAME. &lt;/span&gt;Another &lt;span style="text-decoration:underline;"&gt;UFrame&lt;/span&gt; is used to load &lt;span style="text-decoration:underline;"&gt;AnotherPage.aspx&lt;/span&gt; that shows photos from Flickr.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/omarzabir/WindowsLiveWriter/UFramegoodnessofUpdatePanelandIFRAMEcomb_C197/image_12.png"&gt;&lt;img border="0" width="550" src="http://weblogs.asp.net/blogs/omarzabir/WindowsLiveWriter/UFramegoodnessofUpdatePanelandIFRAMEcomb_C197/image_thumb_5.png" alt="image" height="387" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h3&gt;See it in action!&lt;/h3&gt;
&lt;p&gt;You can test &lt;span style="text-decoration:underline;"&gt;UFrame&lt;/span&gt; from:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a title="UFrame ASP.NET Version" href="http://labs.omaralzabir.com/UFrame2005"&gt;http://labs.omaralzabir.com/UFrame2005&lt;/a&gt; - Visual Studio 2005 version, .NET 2.0 implementation showing regular ASP.NET 2.0 controls work as usual &lt;/li&gt;
&lt;li&gt;&lt;a title="UFrame ASP.NET MVC Version" href="http://labs.omaralzabir.com/UFrameMvc"&gt;http://labs.omaralzabir.com/UFrameMvc&lt;/a&gt; - Visual Studio 2008 version shows ASP.NET MVC works fine making &lt;span style="text-decoration:underline;"&gt;UFrame&lt;/span&gt; an ultimate replacement for &lt;span style="text-decoration:underline;"&gt;UpdatePanel&lt;/span&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;What is UFrame?&lt;/h3&gt;
&lt;p&gt;&lt;span style="text-decoration:underline;"&gt;UFrame &lt;/span&gt;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, &lt;span style="text-decoration:underline;"&gt;UFrame&lt;/span&gt; loads the content within the same document. Thus all the Javascripts, CSS on the main document flows through the loaded content. It&amp;#39;s just like &lt;span style="text-decoration:underline;"&gt;UpdatePanel&lt;/span&gt; with IFRAME&amp;#39;s &lt;span style="text-decoration:underline;"&gt;src &lt;/span&gt;attribute.&lt;/p&gt;
&lt;p&gt;The above &lt;span style="text-decoration:underline;"&gt;UFrames&lt;/span&gt; are declared like this:&lt;/p&gt;
&lt;div&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;UFrame1&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;src&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;SomePage.aspx&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;p&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;This should get replaced with content from Somepage.aspx&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;p&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The features of &lt;span style="text-decoration:underline;"&gt;UFrame&lt;/span&gt; are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;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&amp;#39;s an &lt;span style="text-decoration:underline;"&gt;UpdatePanel&lt;/span&gt;, or simple hyperlinks will behave as if content is being loaded using AJAX. &lt;/li&gt;
&lt;li&gt;Load any URL inside a DIV. It can be a PHP, ASP.NET, JSP or regular HTML page. &lt;/li&gt;
&lt;li&gt;Just like IFRAME, you can set &lt;span style="text-decoration:underline;"&gt;src&lt;/span&gt; property of DIVs and they are converted to &lt;span style="text-decoration:underline;"&gt;UFrame&lt;span style="text-decoration:underline;"&gt;s&lt;/span&gt;&lt;/span&gt; when &lt;span style="text-decoration:underline;"&gt;UFrame&lt;/span&gt; library loads. &lt;/li&gt;
&lt;li&gt;Unlike IFRAME, it loads the content within the main document. So, main document&amp;#39;s CSS and Javascripts are available to the loaded content. &lt;/li&gt;
&lt;li&gt;It allows you to build parts of a page as multiple fully independent pages. &lt;/li&gt;
&lt;li&gt;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 &lt;span style="text-decoration:underline;"&gt;UFrames&lt;/span&gt;. &lt;/li&gt;
&lt;li&gt;It loads and executes both inline and external scripts from loaded page. You can also render different scripts during &lt;span style="text-decoration:underline;"&gt;UFrame&lt;/span&gt; postback. &lt;/li&gt;
&lt;li&gt;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. &lt;/li&gt;
&lt;li&gt;It loads both inline and external CSS. &lt;/li&gt;
&lt;li&gt;It handles duplicates nicely. It does not load the same external Javascript or CSS twice. &lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Download the code&lt;/h3&gt;
&lt;p&gt;You can download latest version of &lt;span style="text-decoration:underline;"&gt;UFrame&lt;/span&gt; along with the VS 2005 and VS 2008 (MVC) example projects from CodePlex:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.codeplex.com/uframe"&gt;www.codeplex.com/uframe&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Please go to the &amp;quot;Source Code&amp;quot; tab for the latest version. You are invited to join the project and improve it or fix bugs.&lt;/p&gt;
&lt;h3&gt;Read the article about UFrame&lt;/h3&gt;
&lt;p&gt;I have published an article about UFrame at CodeProject:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.codeproject.com/KB/aspnet/uframe.aspx"&gt;http://www.codeproject.com/KB/aspnet/uframe.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The article explains in details how the UFrame is built. Be prepared for a big dose of Javascript code. &lt;/p&gt;
&lt;p&gt;If you find UFrame or the article useful, please vote for me at CodeProject.&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.codeproject.com%2fKB%2faspnet%2fuframe.aspx"&gt;&lt;img alt="kick it on DotNetKicks.com" border="0" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.codeproject.com%2fKB%2faspnet%2fuframe.aspx" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1626915" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/javascript/default.aspx">javascript</category><category domain="http://msmvps.com/blogs/omar/archive/tags/ajax/default.aspx">ajax</category></item><item><title>Fast ASP.NET web page loading by downloading multiple javascripts in batch</title><link>http://msmvps.com/blogs/omar/archive/2008/05/10/fast-asp-net-web-page-loading-by-downloading-multiple-javascripts-in-batch.aspx</link><pubDate>Sat, 10 May 2008 00:31:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1618688</guid><dc:creator>omar</dc:creator><slash:comments>23</slash:comments><description>&lt;p&gt;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 &amp;#39;stuck&amp;#39; 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.&lt;/p&gt;
&lt;p&gt;Here&amp;#39;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. &lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/WindowsLiveWriter/Fas.NETwebpageloadingbydeferringandcombi_11F2/Andysnap_003_4.png"&gt;&lt;img alt="Andysnap_003" src="http://msmvps.com/blogs/omar/WindowsLiveWriter/Fas.NETwebpageloadingbydeferringandcombi_11F2/Andysnap_003_thumb_1.png" border="0" width="619" height="269" /&gt;&lt;/a&gt;&lt;br /&gt;Figure: Many scripts downloaded on a typical ASP.NET AJAX page having ASP.NET AJAX Control Toolkit&lt;/p&gt;
&lt;p&gt;As you see, browser gets stuck for 15 times as it downloads and processes external scripts. This makes page loading &amp;quot;feel&amp;quot; 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. &lt;/p&gt;
&lt;p&gt;You pay for such high number of script downloads only because you use two extenders from AJAX Control Toolkit and the &lt;span style="text-decoration:underline;"&gt;UpdatePanel&lt;/span&gt; of ASP.NET AJAX.&lt;/p&gt;
&lt;p&gt;If we can batch the multiple individual script calls into one call like &lt;span style="text-decoration:underline;"&gt;Scripts.ashx&lt;/span&gt; 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. &lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/WindowsLiveWriter/Fas.NETwebpageloadingbydeferringandcombi_11F2/Andysnap_002_4.png"&gt;&lt;img alt="Andysnap_002" src="http://msmvps.com/blogs/omar/WindowsLiveWriter/Fas.NETwebpageloadingbydeferringandcombi_11F2/Andysnap_002_thumb_1.png" border="0" width="499" height="69" /&gt;&lt;/a&gt;&lt;br /&gt;Figure: Download several javascripts over one connection and save call and latency &lt;/p&gt;
&lt;p&gt;The &lt;span style="text-decoration:underline;"&gt;Scripts.ashx&lt;/span&gt; handler can not only download multiple scripts in one shot, but also has a very short URL form. For example:&lt;/p&gt;
&lt;p&gt;&lt;span style="text-decoration:underline;"&gt;/scripts.ashx?initial=a,b,c,d,e&amp;amp;/&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Compared to conventional ASP.NET &lt;span style="text-decoration:underline;"&gt;ScriptResource&lt;/span&gt; URLs like:&lt;/p&gt;
&lt;p&gt;&lt;span style="text-decoration:underline;"&gt;/ScriptResource.axd?d=WzuUYZ-Ggi7-B0tkhjPDTmMmgb5FPLmciWEXQLdjNjt&lt;br /&gt;bmek2jgmm3QETspZjKLvHue5em5kVYJGEuf4kofrcKNL9z6AiMhCe3SrJrcBel_c1&lt;br /&gt;&amp;amp;amp;t=633454272919375000&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The benefits of downloading multiple Javascript over one http call are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;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  &lt;/li&gt;
&lt;li&gt;Create less &amp;quot;pause&amp;quot; moments for the browser. So, browser can fluently render the content of the page and thus give user a fast loading feel  &lt;/li&gt;
&lt;li&gt;Give browser move time and free http connections to download visible artifacts of the page and thus give user a &amp;quot;something&amp;#39;s happening&amp;quot; feel  &lt;/li&gt;
&lt;li&gt;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.  &lt;/li&gt;
&lt;li&gt;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 &lt;span style="text-decoration:underline;"&gt;WebResource.axd&lt;/span&gt; and &lt;span style="text-decoration:underline;"&gt;ScriptResource.axd&lt;/span&gt; URLs that have very large query parameter&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;For example, the homepage of &lt;a href="http://www.dropthings.com"&gt;Dropthings.com&lt;/a&gt; produces the following script tags:&lt;/p&gt;
&lt;div&gt;
&lt;pre class="csharpcode"&gt;&amp;lt;script type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;
...
&lt;span class="rem"&gt;//]]&amp;gt;&lt;/span&gt;
&amp;lt;/script&amp;gt;
&amp;lt;script src=&lt;span class="str"&gt;&amp;quot;/Dropthings/WebResource.axd?d=_w65Lg0FVE-htJvl4_zmXw2&amp;amp;amp;t=633403939286875000&amp;quot;&lt;/span&gt; &lt;br /&gt;type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;
...
&amp;lt;script src=&lt;span class="str"&gt;&amp;quot;Widgets/FastFlickrWidget.js&amp;quot;&lt;/span&gt; type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&lt;span class="str"&gt;&amp;quot;Widgets/FastRssWidget.js&amp;quot;&lt;/span&gt; type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&lt;span class="str"&gt;&amp;quot;/Dropthings/ScriptResource.axd?d=WzuUYZ-Ggi7-B0tkhjPDTmMmgb5FPLmciWEXQLdj&lt;br /&gt;Njtbmek2jgmm3QETspZjKLvHue5em5kVYJGEuf4kofrcKNL9z6AiMhCe3SrJrcBel_c1&lt;br /&gt;&amp;amp;amp;t=633454272919375000&amp;quot;&lt;/span&gt; type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;
&lt;span class="rem"&gt;//&amp;lt;![CDATA[&lt;/span&gt;
...
&amp;lt;/script&amp;gt;
&amp;lt;script src=&lt;span class="str"&gt;&amp;quot;/Dropthings/ScriptResource.axd?d=WzuUYZ-Ggi7-B0tkhjPDTmMmgb5FPLmciWEXQLdjNjtbmek2j&lt;br /&gt;gmm3QETspZjKLvHIbaYWwsewvr_eclXZRGNKzWlaVj44lDEdg9CT2tyH-Yo9jFoQij_XIWxZNETQkZ90&lt;br /&gt;&amp;amp;amp;t=633454272919375000&amp;quot;&lt;/span&gt; type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;
...
&amp;lt;/script&amp;gt;
&amp;lt;script type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;
...
&amp;lt;/script&amp;gt;
&amp;lt;script type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt; charset=&lt;span class="str"&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&amp;gt;
...
&amp;lt;/script&amp;gt;
&amp;lt;script src=&lt;span class="str"&gt;&amp;quot;Myframework.js&amp;quot;&lt;/span&gt; type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;
...
&amp;lt;/script&amp;gt;
&amp;lt;script type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class="kwrd"&gt;if&lt;/span&gt;( &lt;span class="kwrd"&gt;typeof&lt;/span&gt; Proxy == &lt;span class="str"&gt;&amp;quot;undefined&amp;quot;&lt;/span&gt; ) Proxy = ProxyAsync;&amp;lt;/script&amp;gt;
&amp;lt;script type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;
...
&amp;lt;/script&amp;gt;
&amp;lt;script src=&lt;span class="str"&gt;&amp;quot;/Dropthings/ScriptResource.axd?d=WzuUYZ-Ggi7-B0tkhjPDTmMmgb5FPLmciWEXQLdjN&lt;br /&gt;jtbmek2jgmm3QETspZjKLvH-H5JQeA1OWzBaqnbKRQWwc2hxzZ5M8vtSrMhytbB-Oc1&lt;br /&gt;&amp;amp;amp;t=633454272919375000&amp;quot;&lt;/span&gt; type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&lt;span class="str"&gt;&amp;quot;/Dropthings/ScriptResource.axd?d=BXpG1T2rClCdn7QzWc-HrzQ2ECeqBhG6oiVakhRAk&lt;br /&gt;RY6YSaFJsnzqttheoUJJXE4jMUal_1CAxRvbSZ_4_ikAw2&lt;br /&gt;&amp;amp;amp;t=633454540450468750&amp;quot;&lt;/span&gt; type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&lt;span class="str"&gt;&amp;quot;/Dropthings/ScriptResource.axd?d=BXpG1T2rClCdn7QzWc-HrzQ2ECeqBhG6oiVakhRA&lt;br /&gt;kRYRhsy_ZxsfsH4NaPtFtpdDEJ8oZaV5wKE16ikC-hinpw2&lt;br /&gt;&amp;amp;amp;t=633454540450468750&amp;quot;&lt;/span&gt; type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&lt;span class="str"&gt;&amp;quot;/Dropthings/ScriptResource.axd?d=BXpG1T2rClCdn7QzWc-HrzQ2ECeqBhG6oiVakhRAk&lt;br /&gt;RZbimFWogKpiYN4SVreNyf57osSvFc_f24oloxX4RTFfnfj5QsvJGQanl-pbbMbPf01&lt;br /&gt;&amp;amp;amp;t=633454540450468750&amp;quot;&lt;/span&gt; type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;&amp;lt;script type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;
...
&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;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. &lt;/p&gt;
&lt;div&gt;
&lt;pre class="csharpcode"&gt;&lt;p&gt;&amp;lt;script type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;
...
&amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;script type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt; src=&lt;span class="str"&gt;&amp;quot;Scripts.ashx?initial=a,b,c,d,e,f&amp;amp;/dropthings/&amp;quot;&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/b&gt;

&amp;lt;script type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;
...
&amp;lt;/script&amp;gt;

&amp;lt;script type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;
...
&amp;lt;/script&amp;gt;
&amp;lt;script type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;
...
&amp;lt;/script&amp;gt;

&amp;lt;script type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;
...
&amp;lt;/script&amp;gt;

&amp;lt;script type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;&lt;span class="kwrd"&gt;if&lt;/span&gt;( &lt;span class="kwrd"&gt;typeof&lt;/span&gt; Proxy == &lt;span class="str"&gt;&amp;quot;undefined&amp;quot;&lt;/span&gt; ) Proxy = ProxyAsync;&amp;lt;/script&amp;gt;
&amp;lt;script type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;
...
&amp;lt;/script&amp;gt;
&amp;lt;script src=&lt;span class="str"&gt;&amp;quot;/Dropthings/ScriptResource.axd?d=WzuUYZ-...&amp;quot;&lt;/span&gt; type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&lt;span class="str"&gt;&amp;quot;/Dropthings/ScriptResource.axd?d=BXpG1T2...&amp;quot;&lt;/span&gt; type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;b&gt;&amp;lt;script type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt; src=&lt;span class="str"&gt;&amp;quot;Scripts.ashx?post=C,D,E,F,G,H,I,J&amp;amp;/dropthings/&amp;quot;&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/b&gt;

&amp;lt;script type=&lt;span class="str"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&amp;gt;
...
&amp;lt;/script&amp;gt;&lt;/p&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;There are two steps involved here:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Find out all the &lt;span style="text-decoration:underline;"&gt;script&lt;/span&gt; tags being emitted inside generated response HTML and collect them in a buffer. Move them after the visible artifacts in the HTML, especially the &lt;span style="text-decoration:underline;"&gt;&amp;lt;form&amp;gt;&lt;/span&gt; tag that contains the generated output of all ASP.NET controls on the page 
&lt;/li&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The whole solution is explained in this CodeProject article:&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Fast ASP.NET web page loading by downloading multiple javascripts after visible content and in batch&lt;br /&gt;&lt;/b&gt;&lt;a title="http://www.codeproject.com/KB/aspnet/fastload.aspx" href="http://www.codeproject.com/KB/aspnet/fastload.aspx"&gt;http://www.codeproject.com/KB/aspnet/fastload.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;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. &lt;/p&gt;
&lt;p&gt;If you like the idea, please vote for me.&lt;/p&gt;
&lt;p&gt;

&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.codeproject.com%2fKB%2faspnet%2ffastload.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.codeproject.com%2fKB%2faspnet%2ffastload.aspx" alt="kick it on DotNetKicks.com" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1618688" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/performance/default.aspx">performance</category><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/javascript/default.aspx">javascript</category><category domain="http://msmvps.com/blogs/omar/archive/tags/ajax/default.aspx">ajax</category></item><item><title>Fast page loading by moving ASP.NET AJAX scripts after visible content</title><link>http://msmvps.com/blogs/omar/archive/2008/04/06/fast-page-loading-by-postponing-asp-net-ajax-scripts-after-content.aspx</link><pubDate>Sun, 06 Apr 2008 14:49:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1574992</guid><dc:creator>omar</dc:creator><slash:comments>22</slash:comments><description>&lt;p&gt;ASP.NET &lt;u&gt;ScriptManager&lt;/u&gt; control has a property &lt;u&gt;LoadScriptsBeforeUI&lt;/u&gt;, when set to &lt;b&gt;false&lt;/b&gt;, &lt;i&gt;should&lt;/i&gt; load all AJAX framework scripts after the content of the page. But it &lt;strong&gt;does not&lt;/strong&gt; effectively push down all scripts after the content. Some framework scripts, extender scripts and other scripts registered by Ajax Control Toolkit still load before the page content loads. The following screen taken from &lt;a href="http://www.dropthings.com"&gt;www.dropthings.com&lt;/a&gt; shows several script tags are still added at the beginning of &amp;lt;form&amp;gt; which forces them to download first before the page content is loaded and displayed on the page. Script tags pause rendering on several browsers especially in IE until the scripts download and execute. As a result, it gives user a slow loading impression as user stares at a white screen for some time until the scripts before the content download and execute completely. If browser could render the html before it downloads any script, user would see the page content immediately after visiting the site and not see a white screen. This will give user an impression that the website is blazingly fast (just like Google homepage) because user will ideally see the page content, if it&amp;#39;s not too large, immediately after hitting the URL.&lt;/p&gt; &lt;p&gt;&lt;img height="351" alt="image" src="http://omar.mvps.org/images/Fastpageloadi.NETAJAXscriptsaftercontent_C72F/image.png" width="604" /&gt;&lt;br /&gt;Figure: Script blocks being delivered before the content &lt;/p&gt; &lt;p&gt;From the above screen shot you see there are some scripts from ASP.NET AJAX framework and some scripts from Ajax Control Toolkit that are added before the content of the page. Until these scripts download, browser don&amp;#39;t see anything on the UI and thus you get a pause in rendering giving user a slow load feeling. Each script to external URL adds about 200ms avg network roundtrip delay outside USA while it tries to fetch the script. So, user basically stares at a white screen for at least 1.5 sec no matter how fast internet connection he/she has.&lt;/p&gt; &lt;p&gt;These scripts are rendered at the beginning of &lt;u&gt;form&lt;/u&gt; tag because they are registered using &lt;u&gt;Page.ClientScript.RegisterClientScriptBlock&lt;/u&gt;. Inside &lt;u&gt;Page&lt;/u&gt; class of &lt;u&gt;System.Web&lt;/u&gt;, there&amp;#39;s a method &lt;u&gt;BeginFormRender&lt;/u&gt; which renders the client script blocks immediately after the form tag.&lt;/p&gt; &lt;div&gt; &lt;div class="csharpcode"&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   1:&lt;/span&gt; &lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; BeginFormRender(HtmlTextWriter writer, &lt;span class="kwrd"&gt;string&lt;/span&gt; formUniqueID)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   3:&lt;/span&gt;     ...&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4:&lt;/span&gt;         &lt;span class="kwrd"&gt;this&lt;/span&gt;.ClientScript.RenderHiddenFields(writer);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   5:&lt;/span&gt;         &lt;span class="kwrd"&gt;this&lt;/span&gt;.RenderViewStateFields(writer);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   6:&lt;/span&gt;         ...&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   7:&lt;/span&gt;         &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.ClientSupportsJavaScript)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   8:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   9:&lt;/span&gt;             ...&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  10:&lt;/span&gt;             &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;._fRequirePostBackScript)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  11:&lt;/span&gt;             {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  12:&lt;/span&gt;                 &lt;span class="kwrd"&gt;this&lt;/span&gt;.RenderPostBackScript(writer, formUniqueID);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  13:&lt;/span&gt;             }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  14:&lt;/span&gt;             &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;._fRequireWebFormsScript)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  15:&lt;/span&gt;             {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  16:&lt;/span&gt;                 &lt;span class="kwrd"&gt;this&lt;/span&gt;.RenderWebFormsScript(writer);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  17:&lt;/span&gt;             }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  18:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  19:&lt;/span&gt;         &lt;span class="kwrd"&gt;this&lt;/span&gt;.ClientScript.RenderClientScriptBlocks(writer);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  20:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Figure: Decompiled code from &lt;u&gt;System.Web.Page&lt;/u&gt; class&lt;/p&gt;
&lt;p&gt;Here you see several script blocks including scripts registered by calling &lt;u&gt;ClientScript.RegisterClientScriptBlock&lt;/u&gt; are rendered right after &lt;u&gt;form&lt;/u&gt; tag starts.&lt;/p&gt;
&lt;p&gt;There&amp;#39;s no easy work around to override the &lt;u&gt;BeginFormRender&lt;/u&gt; method and defer rendering of these scripts. These rendering functions are buried inside &lt;u&gt;System.Web&lt;/u&gt; and none of these are overridable. So, the only solution seems to be using a Response Filter to capture the html being written and suppress rendering the script blocks until it&amp;#39;s the end of the &lt;u&gt;body&lt;/u&gt; tag. When the &lt;u&gt;&amp;lt;/body&amp;gt;&lt;/u&gt; tag is about to be rendered, we can safely assume page content has been successfully delivered and now all suppressed script blocks can be rendered at once.&lt;/p&gt;
&lt;p&gt;In ASP.NET 2.0, you to create Response Filter which is an implementation of a Stream. You can replace default &lt;u&gt;Response.Filter&lt;/u&gt; with your own stream and then ASP.NET will use your filter to write the final rendered HTML. When &lt;u&gt;Response.Write&lt;/u&gt; is called or &lt;u&gt;Page&amp;#39;&lt;/u&gt;s Render method fires, the response is written to the output stream via the filter. So, you can intercept every byte that&amp;#39;s going to be sent to the client (browser) and modify it the way you like. Response Filters can be used in variety ways to optimize Page output like stripping off all white spaces or doing some formatting on the generated content, or manipulating the characters being sent to the browser and so on.&lt;/p&gt;
&lt;p&gt;I have created a Response filter which captures all characters being sent to the browser. It it finds that script blocks are being rendered, instead of rendering it to the &lt;u&gt;Response.OutputStream&lt;/u&gt;, it will extract the script blocks out of the buffer being written and render the rest of the content. It stores all script blocks, both internal and external, in a string buffer. When it detects &lt;u&gt;&amp;lt;/body&amp;gt;&lt;/u&gt; tag is about to be written to the response, it flushes all the captured script blocks from the string buffer.&lt;/p&gt;
&lt;div&gt;
&lt;div class="csharpcode"&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   1:&lt;/span&gt; &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ScriptDeferFilter : Stream&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   3:&lt;/span&gt;     Stream responseStream;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4:&lt;/span&gt;     &lt;span class="kwrd"&gt;long&lt;/span&gt; position;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   5:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   6:&lt;/span&gt;     &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   7:&lt;/span&gt;     &lt;span class="rem"&gt;/// When this is true, script blocks are suppressed and captured for &lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   8:&lt;/span&gt;     &lt;span class="rem"&gt;/// later rendering&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   9:&lt;/span&gt;     &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  10:&lt;/span&gt;     &lt;span class="kwrd"&gt;bool&lt;/span&gt; captureScripts;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  11:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  12:&lt;/span&gt;     &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  13:&lt;/span&gt;     &lt;span class="rem"&gt;/// Holds all script blocks that are injected by the controls&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  14:&lt;/span&gt;     &lt;span class="rem"&gt;/// The script blocks will be moved after the form tag renders&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  15:&lt;/span&gt;     &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  16:&lt;/span&gt;     StringBuilder scriptBlocks;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  17:&lt;/span&gt;     &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  18:&lt;/span&gt;     Encoding encoding;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  19:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  20:&lt;/span&gt;     &lt;span class="kwrd"&gt;public&lt;/span&gt; ScriptDeferFilter(Stream inputStream, HttpResponse response)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  21:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  22:&lt;/span&gt;         &lt;span class="kwrd"&gt;this&lt;/span&gt;.encoding = response.Output.Encoding;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  23:&lt;/span&gt;         &lt;span class="kwrd"&gt;this&lt;/span&gt;.responseStream = response.Filter;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  24:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  25:&lt;/span&gt;         &lt;span class="kwrd"&gt;this&lt;/span&gt;.scriptBlocks = &lt;span class="kwrd"&gt;new&lt;/span&gt; StringBuilder(5000);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  26:&lt;/span&gt;         &lt;span class="rem"&gt;// When this is on, script blocks are captured and not written to output&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  27:&lt;/span&gt;         &lt;span class="kwrd"&gt;this&lt;/span&gt;.captureScripts = &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  28:&lt;/span&gt;     }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Here&amp;#39;s the beginning of the Filter class. When it initializes, it takes the original Response Filter. Then it overrides the &lt;u&gt;Write&lt;/u&gt; method of the Stream so that it can capture the buffers being written and do it&amp;#39;s own processing. &lt;/p&gt;
&lt;div&gt;
&lt;div class="csharpcode"&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   1:&lt;/span&gt; &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Write(&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] buffer, &lt;span class="kwrd"&gt;int&lt;/span&gt; offset, &lt;span class="kwrd"&gt;int&lt;/span&gt; count)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   3:&lt;/span&gt;     &lt;span class="rem"&gt;// If we are not capturing script blocks anymore, just redirect to response stream&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4:&lt;/span&gt;     &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;this&lt;/span&gt;.captureScripts)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   5:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   6:&lt;/span&gt;         &lt;span class="kwrd"&gt;this&lt;/span&gt;.responseStream.Write(buffer, offset, count);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   7:&lt;/span&gt;         &lt;span class="kwrd"&gt;return&lt;/span&gt;;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   8:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   9:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  10:&lt;/span&gt;     &lt;span class="rem"&gt;/* &lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  11:&lt;/span&gt; &lt;span class="rem"&gt;     * Script and HTML can be in one of the following combinations in the specified buffer:          &lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  12:&lt;/span&gt; &lt;span class="rem"&gt;     * .....&amp;lt;script ....&amp;gt;.....&amp;lt;/script&amp;gt;.....&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  13:&lt;/span&gt; &lt;span class="rem"&gt;     * &amp;lt;script ....&amp;gt;.....&amp;lt;/script&amp;gt;.....&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  14:&lt;/span&gt; &lt;span class="rem"&gt;     * &amp;lt;script ....&amp;gt;.....&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  15:&lt;/span&gt; &lt;span class="rem"&gt;     * &amp;lt;script ....&amp;gt;.....&amp;lt;/script&amp;gt; .....&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  16:&lt;/span&gt; &lt;span class="rem"&gt;     * ....&amp;lt;script ....&amp;gt;..... &lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  17:&lt;/span&gt; &lt;span class="rem"&gt;     * &amp;lt;script ....&amp;gt;..... &lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  18:&lt;/span&gt; &lt;span class="rem"&gt;     * .....&amp;lt;/script&amp;gt;.....&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  19:&lt;/span&gt; &lt;span class="rem"&gt;     * .....&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  20:&lt;/span&gt; &lt;span class="rem"&gt;     * &amp;lt;script&amp;gt;.....&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  21:&lt;/span&gt; &lt;span class="rem"&gt;     * .... &amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  22:&lt;/span&gt; &lt;span class="rem"&gt;     * ......&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  23:&lt;/span&gt; &lt;span class="rem"&gt;     * Here, &amp;quot;....&amp;quot; means html content between and outside script tags&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  24:&lt;/span&gt; &lt;span class="rem"&gt;    */&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  25:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  26:&lt;/span&gt;     &lt;span class="kwrd"&gt;char&lt;/span&gt;[] content = &lt;span class="kwrd"&gt;this&lt;/span&gt;.encoding.GetChars(buffer, offset, count);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  27:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  28:&lt;/span&gt;     &lt;span class="kwrd"&gt;int&lt;/span&gt; scriptTagStart = 0;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  29:&lt;/span&gt;     &lt;span class="kwrd"&gt;int&lt;/span&gt; lastScriptTagEnd = 0;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  30:&lt;/span&gt;     &lt;span class="kwrd"&gt;bool&lt;/span&gt; scriptTagStarted = &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  31:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  32:&lt;/span&gt;     &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; pos = 0; pos &amp;lt; content.Length; pos++)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  33:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  34:&lt;/span&gt;         &lt;span class="rem"&gt;// See if tag start&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  35:&lt;/span&gt;         &lt;span class="kwrd"&gt;char&lt;/span&gt; c = content[pos];&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  36:&lt;/span&gt;         &lt;span class="kwrd"&gt;if&lt;/span&gt; (c == &lt;span class="str"&gt;&amp;#39;&amp;lt;&amp;#39;&lt;/span&gt;)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  37:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  38:&lt;/span&gt;             &lt;span class="kwrd"&gt;int&lt;/span&gt; tagStart = pos;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  39:&lt;/span&gt;             &lt;span class="rem"&gt;// Check if it&amp;#39;s a tag ending&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  40:&lt;/span&gt;             &lt;span class="kwrd"&gt;if&lt;/span&gt; (content[pos+1] == &lt;span class="str"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  41:&lt;/span&gt;             {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  42:&lt;/span&gt;                 pos+=2; &lt;span class="rem"&gt;// go past the &amp;lt;/ &lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  43:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  44:&lt;/span&gt;                 &lt;span class="rem"&gt;// See if script tag is ending&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  45:&lt;/span&gt;                 &lt;span class="kwrd"&gt;if&lt;/span&gt; (isScriptTag(content, pos))&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  46:&lt;/span&gt;                 {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  47:&lt;/span&gt;                     &lt;span class="rem"&gt;/// Script tag just ended. Get the whole script&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  48:&lt;/span&gt;                     &lt;span class="rem"&gt;/// and store in buffer&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  49:&lt;/span&gt;                     pos = pos + &lt;span class="str"&gt;&amp;quot;script&amp;gt;&amp;quot;&lt;/span&gt;.Length;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  50:&lt;/span&gt;                     scriptBlocks.Append(content, scriptTagStart, pos - scriptTagStart);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  51:&lt;/span&gt;                     scriptBlocks.Append(Environment.NewLine);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  52:&lt;/span&gt;                     lastScriptTagEnd = pos;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  53:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  54:&lt;/span&gt;                     scriptTagStarted = &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  55:&lt;/span&gt;                     &lt;span class="kwrd"&gt;continue&lt;/span&gt;;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  56:&lt;/span&gt;                 }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  57:&lt;/span&gt;                 &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (isBodyTag(content, pos))&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  58:&lt;/span&gt;                 {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  59:&lt;/span&gt;                     &lt;span class="rem"&gt;/// body tag has just end. Time for rendering all the script&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  60:&lt;/span&gt;                     &lt;span class="rem"&gt;/// blocks we have suppressed so far and stop capturing script blocks&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  61:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  62:&lt;/span&gt;                     &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.scriptBlocks.Length &amp;gt; 0)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  63:&lt;/span&gt;                     {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  64:&lt;/span&gt;                         &lt;span class="rem"&gt;// Render all pending html output till now&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  65:&lt;/span&gt;                         &lt;span class="kwrd"&gt;this&lt;/span&gt;.WriteOutput(content, lastScriptTagEnd, tagStart - lastScriptTagEnd);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  66:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  67:&lt;/span&gt;                         &lt;span class="rem"&gt;// Render the script blocks&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  68:&lt;/span&gt;                         &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] scriptBytes = &lt;span class="kwrd"&gt;this&lt;/span&gt;.encoding.GetBytes(&lt;span class="kwrd"&gt;this&lt;/span&gt;.scriptBlocks.ToString());&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  69:&lt;/span&gt;                         &lt;span class="kwrd"&gt;this&lt;/span&gt;.responseStream.Write(scriptBytes, 0, scriptBytes.Length);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  70:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  71:&lt;/span&gt;                         &lt;span class="rem"&gt;// Stop capturing for script blocks&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  72:&lt;/span&gt;                         &lt;span class="kwrd"&gt;this&lt;/span&gt;.captureScripts = &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  73:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  74:&lt;/span&gt;                         &lt;span class="rem"&gt;// Write from the body tag start to the end of the inut buffer and return&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  75:&lt;/span&gt;                         &lt;span class="rem"&gt;// from the function. We are done.&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  76:&lt;/span&gt;                         &lt;span class="kwrd"&gt;this&lt;/span&gt;.WriteOutput(content, tagStart, content.Length - tagStart);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  77:&lt;/span&gt;                         &lt;span class="kwrd"&gt;return&lt;/span&gt;;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  78:&lt;/span&gt;                     }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  79:&lt;/span&gt;                 }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  80:&lt;/span&gt;                 &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  81:&lt;/span&gt;                 {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  82:&lt;/span&gt;                     &lt;span class="rem"&gt;// some other tag&amp;#39;s closing. safely skip one character as smallest&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  83:&lt;/span&gt;                     &lt;span class="rem"&gt;// html tag is one character e.g. &amp;lt;b&amp;gt;. just an optimization to save one loop&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  84:&lt;/span&gt;                     pos++;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  85:&lt;/span&gt;                 }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  86:&lt;/span&gt;             }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  87:&lt;/span&gt;             &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  88:&lt;/span&gt;             {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  89:&lt;/span&gt;                 &lt;span class="kwrd"&gt;if&lt;/span&gt; (isScriptTag(content, pos+1))&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  90:&lt;/span&gt;                 {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  91:&lt;/span&gt;                     &lt;span class="rem"&gt;/// Script tag started. Record the position as we will &lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  92:&lt;/span&gt;                     &lt;span class="rem"&gt;/// capture the whole script tag including its content&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  93:&lt;/span&gt;                     &lt;span class="rem"&gt;/// and store in an internal buffer.&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  94:&lt;/span&gt;                     scriptTagStart = pos;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  95:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  96:&lt;/span&gt;                     &lt;span class="rem"&gt;// Write html content since last script tag closing upto this script tag &lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  97:&lt;/span&gt;                     &lt;span class="kwrd"&gt;this&lt;/span&gt;.WriteOutput(content, lastScriptTagEnd, scriptTagStart - lastScriptTagEnd);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  98:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  99:&lt;/span&gt;                     &lt;span class="rem"&gt;// Skip the tag start to save some loops&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 100:&lt;/span&gt;                     pos += &lt;span class="str"&gt;&amp;quot;&amp;lt;script&amp;quot;&lt;/span&gt;.Length;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 101:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 102:&lt;/span&gt;                     scriptTagStarted = &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 103:&lt;/span&gt;                 }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 104:&lt;/span&gt;                 &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 105:&lt;/span&gt;                 {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 106:&lt;/span&gt;                     &lt;span class="rem"&gt;// some other tag started&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 107:&lt;/span&gt;                     &lt;span class="rem"&gt;// safely skip 2 character because the smallest tag is one character e.g. &amp;lt;b&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 108:&lt;/span&gt;                     &lt;span class="rem"&gt;// just an optimization to eliminate one loop &lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 109:&lt;/span&gt;                     pos++;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 110:&lt;/span&gt;                 }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 111:&lt;/span&gt;             }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 112:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 113:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 114:&lt;/span&gt;     &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 115:&lt;/span&gt;     &lt;span class="rem"&gt;// If a script tag is partially sent to buffer, then the remaining content&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 116:&lt;/span&gt;     &lt;span class="rem"&gt;// is part of the last script block&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 117:&lt;/span&gt;     &lt;span class="kwrd"&gt;if&lt;/span&gt; (scriptTagStarted)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 118:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 119:&lt;/span&gt;         &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 120:&lt;/span&gt;         &lt;span class="kwrd"&gt;this&lt;/span&gt;.scriptBlocks.Append(content, scriptTagStart, content.Length - scriptTagStart);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 121:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 122:&lt;/span&gt;     &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 123:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 124:&lt;/span&gt;         &lt;span class="rem"&gt;/// Render the characters since the last script tag ending&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 125:&lt;/span&gt;         &lt;span class="kwrd"&gt;this&lt;/span&gt;.WriteOutput(content, lastScriptTagEnd, content.Length - lastScriptTagEnd);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 126:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 127:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;There are several situations to consider here. The &lt;u&gt;Write&lt;/u&gt; method is called several times during the Page render process because the generated HTML can be quite big. So, it will contain partial HTML. So, it&amp;#39;s possible the first Write call contains a start of a script block, but no ending script tag. The following Write call may or may not have the ending script block. So, we need to preserve state to make sure we don&amp;#39;t overlook any script block. Each &lt;u&gt;Write&lt;/u&gt; call can have several script block in the buffer as well. It can also have no script block and only page content.&lt;/p&gt;
&lt;p&gt;The idea here is to go through each character and see if there&amp;#39;s any starting script tag. If there is, remember the start position of the script tag. If script end tag is found within the buffer, then extract out the whole script block from the buffer and render the remaining html. If there&amp;#39;s no ending tag found but a script tag did start within the buffer, then suppress output and capture the remaining content within the script buffer so that next call to &lt;u&gt;Write&lt;/u&gt; method can grab the remaining script and extract it out from the output.&lt;/p&gt;
&lt;p&gt;There are two other private functions that are basically helper functions and does not do anything interesting:&lt;/p&gt;
&lt;div&gt;
&lt;div class="csharpcode"&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   1:&lt;/span&gt; &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; WriteOutput(&lt;span class="kwrd"&gt;char&lt;/span&gt;[] content, &lt;span class="kwrd"&gt;int&lt;/span&gt; pos, &lt;span class="kwrd"&gt;int&lt;/span&gt; length)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   3:&lt;/span&gt;     &lt;span class="kwrd"&gt;if&lt;/span&gt; (length == 0) &lt;span class="kwrd"&gt;return&lt;/span&gt;;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   5:&lt;/span&gt;     &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] buffer = &lt;span class="kwrd"&gt;this&lt;/span&gt;.encoding.GetBytes(content, pos, length);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   6:&lt;/span&gt;     &lt;span class="kwrd"&gt;this&lt;/span&gt;.responseStream.Write(buffer, 0, buffer.Length);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   7:&lt;/span&gt; }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   8:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   9:&lt;/span&gt; &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; isScriptTag(&lt;span class="kwrd"&gt;char&lt;/span&gt;[] content, &lt;span class="kwrd"&gt;int&lt;/span&gt; pos)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  10:&lt;/span&gt; {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  11:&lt;/span&gt;     &lt;span class="kwrd"&gt;if&lt;/span&gt; (pos + 5 &amp;lt; content.Length)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  12:&lt;/span&gt;         &lt;span class="kwrd"&gt;return&lt;/span&gt; ((content[pos] == &lt;span class="str"&gt;&amp;#39;s&amp;#39;&lt;/span&gt; || content[pos] == &lt;span class="str"&gt;&amp;#39;S&amp;#39;&lt;/span&gt;)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  13:&lt;/span&gt;             &amp;amp;&amp;amp; (content[pos + 1] == &lt;span class="str"&gt;&amp;#39;c&amp;#39;&lt;/span&gt; || content[pos + 1] == &lt;span class="str"&gt;&amp;#39;C&amp;#39;&lt;/span&gt;)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  14:&lt;/span&gt;             &amp;amp;&amp;amp; (content[pos + 2] == &lt;span class="str"&gt;&amp;#39;r&amp;#39;&lt;/span&gt; || content[pos + 2] == &lt;span class="str"&gt;&amp;#39;R&amp;#39;&lt;/span&gt;)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  15:&lt;/span&gt;             &amp;amp;&amp;amp; (content[pos + 3] == &lt;span class="str"&gt;&amp;#39;i&amp;#39;&lt;/span&gt; || content[pos + 3] == &lt;span class="str"&gt;&amp;#39;I&amp;#39;&lt;/span&gt;)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  16:&lt;/span&gt;             &amp;amp;&amp;amp; (content[pos + 4] == &lt;span class="str"&gt;&amp;#39;p&amp;#39;&lt;/span&gt; || content[pos + 4] == &lt;span class="str"&gt;&amp;#39;P&amp;#39;&lt;/span&gt;)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  17:&lt;/span&gt;             &amp;amp;&amp;amp; (content[pos + 5] == &lt;span class="str"&gt;&amp;#39;t&amp;#39;&lt;/span&gt; || content[pos + 5] == &lt;span class="str"&gt;&amp;#39;T&amp;#39;&lt;/span&gt;));&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  18:&lt;/span&gt;     &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  19:&lt;/span&gt;         &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  20:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  21:&lt;/span&gt; }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  22:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  23:&lt;/span&gt; &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; isBodyTag(&lt;span class="kwrd"&gt;char&lt;/span&gt;[] content, &lt;span class="kwrd"&gt;int&lt;/span&gt; pos)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  24:&lt;/span&gt; {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  25:&lt;/span&gt;     &lt;span class="kwrd"&gt;if&lt;/span&gt; (pos + 3 &amp;lt; content.Length)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  26:&lt;/span&gt;         &lt;span class="kwrd"&gt;return&lt;/span&gt; ((content[pos] == &lt;span class="str"&gt;&amp;#39;b&amp;#39;&lt;/span&gt; || content[pos] == &lt;span class="str"&gt;&amp;#39;B&amp;#39;&lt;/span&gt;)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  27:&lt;/span&gt;             &amp;amp;&amp;amp; (content[pos + 1] == &lt;span class="str"&gt;&amp;#39;o&amp;#39;&lt;/span&gt; || content[pos + 1] == &lt;span class="str"&gt;&amp;#39;O&amp;#39;&lt;/span&gt;)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  28:&lt;/span&gt;             &amp;amp;&amp;amp; (content[pos + 2] == &lt;span class="str"&gt;&amp;#39;d&amp;#39;&lt;/span&gt; || content[pos + 2] == &lt;span class="str"&gt;&amp;#39;D&amp;#39;&lt;/span&gt;)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  29:&lt;/span&gt;             &amp;amp;&amp;amp; (content[pos + 3] == &lt;span class="str"&gt;&amp;#39;y&amp;#39;&lt;/span&gt; || content[pos + 3] == &lt;span class="str"&gt;&amp;#39;Y&amp;#39;&lt;/span&gt;));&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  30:&lt;/span&gt;     &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  31:&lt;/span&gt;         &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  32:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The &lt;u&gt;isScriptTag&lt;/u&gt; and &lt;u&gt;isBodyTag&lt;/u&gt; functions may look weird. The reason for such weird code is pure performance. Instead of doing fancy checks like taking a part of the array out and doing string comparison, this is the fastest way of doing the check. Best thing about .NET IL is that it&amp;#39;s optimized, if any of the condition in the &amp;amp;&amp;amp; pairs fail, it won&amp;#39;t even execute the rest. So, this is&amp;nbsp; as best as it can get to check for certain characters.&lt;/p&gt;
&lt;p&gt;There are some corner cases that are not handled here. For example, what if the buffer contains a partial script tag declaration. For example, &lt;u&gt;&amp;quot;....&amp;lt;scr&amp;quot;&lt;/u&gt; and that&amp;#39;s it. The remaining characters did not finish in the buffer instead next buffer is sent with the remaining characters like &lt;u&gt;&amp;quot;ipt src=&amp;quot;...&amp;quot; &amp;gt;.....&amp;lt;/scrip&amp;quot;&lt;/u&gt;. In such case, the script tag won&amp;#39;t be taken out. One way to handle this would be to make sure you always have enough characters left in the buffer to do a complete tag name check. If not found, store the half finished buffer somewhere and on next call to Write, combine it with the new buffer sent and do the processing.&lt;/p&gt;
&lt;p&gt;In order to install the Filter, you need to hook it in in the Global.asax BeginRequest or some other event that&amp;#39;s fired before the Response is generated.&lt;/p&gt;
&lt;div&gt;
&lt;div class="csharpcode"&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   1:&lt;/span&gt; &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Application_BeginRequest(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   3:&lt;/span&gt;     &lt;span class="kwrd"&gt;if&lt;/span&gt; (Request.HttpMethod == &lt;span class="str"&gt;&amp;quot;GET&amp;quot;&lt;/span&gt;)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   5:&lt;/span&gt;         &lt;span class="kwrd"&gt;if&lt;/span&gt; (Request.AppRelativeCurrentExecutionFilePath.EndsWith(&lt;span class="str"&gt;&amp;quot;.aspx&amp;quot;&lt;/span&gt;))&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   6:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   7:&lt;/span&gt;             Response.Filter = &lt;span class="kwrd"&gt;new&lt;/span&gt; ScriptDeferFilter(Response);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   8:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   9:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  10:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Here I am hooking the Filter only for &lt;u&gt;GET&lt;/u&gt; calls to &lt;u&gt;.aspx&lt;/u&gt; pages. You can hook it to POST calls as well. But asynchronous postbacks are regular &lt;u&gt;POST&lt;/u&gt; and I do not want to do any change in the generated JSON or html fragment. Another way is to hook the filter only when &lt;u&gt;ContentType&lt;/u&gt; is &lt;u&gt;text/html&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;When this filter is installed, &lt;a href="http://www.dropthings.com"&gt;www.dropthings.com&lt;/a&gt; defers all script loading after the &amp;lt;form&amp;gt; tag completes.&lt;/p&gt;
&lt;p&gt;&lt;img height="224" alt="image" src="http://omar.mvps.org/images/Fastpageloadi.NETAJAXscriptsaftercontent_C72F/image_3.png" width="635" /&gt; &lt;br /&gt;Figure: Script tags are moved after the &amp;lt;form&amp;gt; tag when the filter is used&lt;/p&gt;
&lt;p&gt;You can grab the Filter class from the &lt;u&gt;App_Code\ScriptDeferFilter.cs&lt;/u&gt; of the Dropthings project. Go to &lt;a href="http://www.codeplex.com/dropthings"&gt;CodePlex&lt;/a&gt; site and download the latest code for the latest filter.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1574992" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/performance/default.aspx">performance</category><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/javascript/default.aspx">javascript</category><category domain="http://msmvps.com/blogs/omar/archive/tags/ajax/default.aspx">ajax</category></item><item><title>On-demand UI loading on AJAX websites</title><link>http://msmvps.com/blogs/omar/archive/2007/11/09/on-demand-ui-loading-on-ajax-websites.aspx</link><pubDate>Fri, 09 Nov 2007 09:01:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1289498</guid><dc:creator>omar</dc:creator><slash:comments>8</slash:comments><description>&lt;p&gt;AJAX websites are all about loading as many features as possible
into the browser without having any postback. If you look at the
Start Pages like 
&lt;a href="http://www.pageflakes.com"&gt;Pageflakes&lt;/a&gt;, it&amp;#39;s only one
single page that gives you all the features of the whole
application with zero postback. A quick and dirty approach for
doing this is to deliver every possible html snippets inside hidden
divs during page load and then make those divs visible when needed.
But this makes first time loading way too long and browser gives
sluggish performance as too much stuff is on the DOM. So, a better
approach is to load html snippet and necessary javascript
on-demand. In my 
&lt;a href="http://www.dropthings.com"&gt;dropthings&lt;/a&gt; project, I have
shown an example how this is done.&lt;/p&gt;
&lt;p&gt;
&lt;img height="424" alt="clip_image002" src="http://omar.mvps.org/images/IncrementalUIloadingonAJAXwebsites_12E95/clip_image002.gif" width="480" /&gt;
&lt;/p&gt;
&lt;p&gt;When you click on the &amp;quot;help&amp;quot; link, it loads the content of the
help dynamically. This html is not delivered as part of the 
&lt;u&gt;default.aspx&lt;/u&gt; that renders the first page. Thus the giant
html and graphics related to the help section has no effect on site
load performance. It is only loaded when user clicks the &amp;quot;help&amp;quot;
link. Moreover, it gets cached on the browser and thus loads only
once. When user clicks the &amp;quot;help&amp;quot; link again, it&amp;#39;s served directly
from the browser cache, instead of fetching from the origin server
again.&lt;/p&gt;
&lt;p&gt;The principle is making an XMLHTTP call to an 
&lt;u&gt;.aspx&lt;/u&gt; page, get the response html, put that response html
inside a container DIV, make that DIV visible.&lt;/p&gt;
&lt;p&gt;AJAX framework has a 
&lt;u&gt;Sys.Net.WebRequest&lt;/u&gt; class which you can use to make regular
HTTP calls. You can define http method, URI, headers and the body
of the call. It&amp;rsquo;s kind of a low level function for making
direct calls via XMLHTTP. Once you construct a web request, you can
execute it using 
&lt;u&gt;Sys.Net.XMLHttpExecutor&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   1:&lt;/span&gt; function showHelp()
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   2:&lt;/span&gt; {
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   3:&lt;/span&gt;     var request = 
&lt;span class="kwrd"&gt;new&lt;/span&gt; Sys.Net.WebRequest();
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   4:&lt;/span&gt;     request.set_httpVerb(
&lt;span class="str"&gt;&amp;quot;GET&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   5:&lt;/span&gt;     request.set_url(
&lt;span class="str"&gt;&amp;#39;help.aspx&amp;#39;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   6:&lt;/span&gt;     request.add_completed(
function( executor )
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   7:&lt;/span&gt;     {
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   8:&lt;/span&gt;         
&lt;span class="kwrd"&gt;if&lt;/span&gt; (executor.get_responseAvailable()) 
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   9:&lt;/span&gt;         {
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  10:&lt;/span&gt;             var helpDiv = $get(
&lt;span class="str"&gt;&amp;#39;HelpDiv&amp;#39;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  11:&lt;/span&gt;             var helpLink = $get(
&lt;span class="str"&gt;&amp;#39;HelpLink&amp;#39;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  12:&lt;/span&gt;             
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  13:&lt;/span&gt;             var helpLinkBounds =
Sys.UI.DomElement.getBounds(helpLink);
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  14:&lt;/span&gt;             
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  15:&lt;/span&gt;             helpDiv.style.top =
(helpLinkBounds.y + helpLinkBounds.height) + 
&lt;span class="str"&gt;&amp;quot;px&amp;quot;&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  16:&lt;/span&gt;             
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  17:&lt;/span&gt;             var content =
executor.get_responseData();
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  18:&lt;/span&gt;             helpDiv.innerHTML =
content;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  19:&lt;/span&gt;             helpDiv.style.display =

&lt;span class="str"&gt;&amp;quot;block&amp;quot;&lt;/span&gt;;                       
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  20:&lt;/span&gt;         }
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  21:&lt;/span&gt;     });
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  22:&lt;/span&gt;     
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  23:&lt;/span&gt;     var executor = 
&lt;span class="kwrd"&gt;new&lt;/span&gt; Sys.Net.XMLHttpExecutor();
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  24:&lt;/span&gt;     request.set_executor(executor);

&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  25:&lt;/span&gt;     executor.executeRequest();
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  26:&lt;/span&gt; }
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The example shows how the help section is loaded by hitting 
&lt;u&gt;help.aspx&lt;/u&gt; and injecting its response inside the 
&lt;u&gt;HelpDiv&lt;/u&gt;. The response can be cached by the 
&lt;a&gt;output cache directive&lt;/a&gt; set on 
&lt;u&gt;help.aspx&lt;/u&gt;. So, next time when user clicks on the link, the
UI pops up immediately. The 
&lt;u&gt;help.aspx&lt;/u&gt; file has no 
&lt;u&gt;&amp;lt;html&amp;gt;&lt;/u&gt; block, only the content that is set inside the 
&lt;a&gt;DIV&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   1:&lt;/span&gt; 
&lt;span class="asp"&gt;&amp;lt;%@ Page Language=&amp;quot;C#&amp;quot; AutoEventWireup=&amp;quot;true&amp;quot;
CodeFile=&amp;quot;Help.aspx.cs&amp;quot; Inherits=&amp;quot;Help&amp;quot; %&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   2:&lt;/span&gt; 
&lt;span class="asp"&gt;&amp;lt;%@ OutputCache Location=&amp;quot;ServerAndClient&amp;quot;
Duration=&amp;quot;604800&amp;quot; VaryByParam=&amp;quot;none&amp;quot; %&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   3:&lt;/span&gt; 
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;
&lt;span class="html"&gt;div&lt;/span&gt; 
&lt;span class="attr"&gt;class&lt;/span&gt;
&lt;span class="kwrd"&gt;=&amp;quot;helpContent&amp;quot;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   4:&lt;/span&gt; 
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;
&lt;span class="html"&gt;div&lt;/span&gt; 
&lt;span class="attr"&gt;id&lt;/span&gt;
&lt;span class="kwrd"&gt;=&amp;quot;lipsum&amp;quot;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   5:&lt;/span&gt; 
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;
&lt;span class="html"&gt;p&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   6:&lt;/span&gt; Lorem ipsum dolor sit amet,
consectetuer adipiscing elit. Duis lorem
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   7:&lt;/span&gt; eros, volutpat sit amet, venenatis
vitae, condimentum at, dolor. Nunc
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   8:&lt;/span&gt; porttitor eleifend tellus. Praesent
vitae neque ut mi rutrum cursus.
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Using this approach, you can break the UI into smaller 
&lt;u&gt;.aspx&lt;/u&gt; files. Although these 
&lt;u&gt;.aspx&lt;/u&gt; files cannot have JavaScript or stylesheet blocks, but
they can contain large amount of html that you need to show on the
UI on-demand. Thus you can keep initial download to absolute
minimum just for loading the basic stuffs. When user explores new
features on the site, load those areas incrementally.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1289498" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/javascript/default.aspx">javascript</category><category domain="http://msmvps.com/blogs/omar/archive/tags/ajax/default.aspx">ajax</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category></item><item><title>10 cool web development related articles in 2007</title><link>http://msmvps.com/blogs/omar/archive/2007/10/02/10-cool-web-development-related-articles-in-2007.aspx</link><pubDate>Tue, 02 Oct 2007 17:26:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1225686</guid><dc:creator>omar</dc:creator><slash:comments>8</slash:comments><description>&lt;p&gt;Here&amp;#39;s a list of 10 cool ASP.NET, AJAX and web development related articles and blog posts that I have written this year that you might want to take a look:&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.codeproject.com/install/13disasters.asp"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.codeproject.com/install/13disasters.asp"&gt;13 disasters for production website and their solutions&lt;/a&gt; &lt;br /&gt;Talks about 13 production disasters that can happen to any website any time and bring down your business.&amp;nbsp;&lt;/p&gt;&lt;a href="http://www.codeproject.com/Ajax/MakingGoogleIG.asp"&gt;Build Google IG like Ajax Start Page in 7 days using ASP.NET Ajax and .NET 3.0&lt;/a&gt; &lt;br /&gt;This block buster article shows how ASP.NET AJAX, Linq to XML, Linq to SQL and Workflow Foundation can be used to create a Google IG like start page in just 7 nights. Learn how to put together such hot technologies into one project and make a production site out of it.  &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/04/29/serve-extensionless-url-from-asp-net-without-using-isapi-module-or-iis-6-wildcard-mapping.aspx"&gt;Serve extensionless URL from ASP.NET without using ISAPI module or IIS 6 Wildcard mapping&lt;/a&gt; &lt;br /&gt;Currently there are only two ways to service extentionless URL like &lt;a href="http://www.pageflakes.com/omar"&gt;www.pageflakes.com/omar&lt;/a&gt; that hits something besides the default document - use a custom ISAPI module or use IIS 6 wildcard mapping. Both has performance and scalability problems because both intercepts each and every hit. Learn how you can solve it by using a custom 404 handler.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/09/19/request-format-is-unrecognized-for-url-unexpectedly-ending-in-somewebservicemethod.aspx"&gt;Request format is unrecognized for URL unexpectedly ending in /SomeWebServiceMethod&lt;/a&gt; &lt;br /&gt;Since ASP.NET AJAX 1.0 release, Microsoft prevented JSON hijacking by adding a special content type header. But this caused us some trouble. &lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/03/25/cleanup-inactive-anonymous-users-from-asp-net-membership-tables.aspx"&gt;Cleanup inactive anonymous users from ASP.NET Membership Tables&lt;/a&gt; &lt;br /&gt;When you store anonymous user profile using ASP.NET Membership provider and Anonymous Identification provider, you soon end up with lots of idle anonymous user data where those users never come back. We (Pageflakes) went through a lot of difficulty keeping our database size down as we allow anonymous users to do almost everything that a registered user can do. This introduces scalability challenge. See how we solved this problem.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/03/24/prevent-denial-of-service-dos-attacks-in-your-web-application.aspx"&gt;Prevent Denial of Service (DOS) attacks in your web application&lt;/a&gt; &lt;br /&gt;Web applications can be brought down to its knees by hitting the site repeatedly or by calling expensive webservices randomly. Anyone can write a simple loop that hits a webserver very frequently from a high bandwidth connectivity and bring your production server down. See how to prevent such application level DOS attacks.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/03/22/asp-net-ajax-extender-for-multi-column-widget-drag-drop.aspx"&gt;ASP.NET Ajax Extender for multi-column widget drag &amp;amp; drop&lt;/a&gt; &lt;br /&gt;It&amp;#39;s an ASP.NET AJAX extender that allows Pageflakes style drag &amp;amp; drop functionality between columns and rows. &lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/03/16/asp-net-ajax-in-depth-performance-analysis.aspx"&gt;ASP.NET Ajax in-depth performance analysis&lt;/a&gt; &lt;br /&gt;While building an open source start page using ASP.NET AJAX, I have done a lot of performance analysis on AJAX framework in order to improve first time load and perceived speed of javascript rich pages. Check out my analysis.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/01/20/think-you-know-how-to-write-update-statement-think-again.aspx"&gt;Think you know how to write UPDATE statement? Think again.&lt;/a&gt; &lt;br /&gt;Learn how to optimize common UPDATE statements&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/01/07/make-a-surveillance-application-which-captures-desktop-and-emails-you-as-attachment.aspx"&gt;Make a surveillance application which captures desktop and then emails you as attachment&lt;/a&gt; &lt;br /&gt;Some time back I needed to capture a certain computers desktop in order to find out what that user is doing every day. So, I made a .NET 2.0 Winforms Application which stays on system tray (optional) and capture the desktop in given time interval (say every 60 secs) and emailed the captured images to me as message attachment (say every 30 mins).&lt;/p&gt; &lt;hr /&gt;  &lt;p&gt;Today I received MVP award for the 3rd time on Visual C#. Thanks to Microsoft for the award and setting up my &lt;a href="http://weblogs.asp.net/omarzabir"&gt;new blog&lt;/a&gt;. I will continue both my &lt;a href="http://msmvps.com/omar"&gt;MVPS Blog&lt;/a&gt; and this blog from now on.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1225686" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/production/default.aspx">production</category><category domain="http://msmvps.com/blogs/omar/archive/tags/javascript/default.aspx">javascript</category><category domain="http://msmvps.com/blogs/omar/archive/tags/ajax/default.aspx">ajax</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category></item><item><title>Loading JSON via &lt;SCRIPT&gt; tag: Problem with HTML in JSON</title><link>http://msmvps.com/blogs/omar/archive/2006/08/06/loading-json-via-lt-script-gt-tag-problem-with-html-in-json.aspx</link><pubDate>Sun, 06 Aug 2006 16:21:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:106889</guid><dc:creator>omar</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;Just a precaution note to those who are trying to load JSON using &amp;lt;SCRIPT&amp;gt; tag. Don’t do it. Use XMLHTTP. In &lt;a href="http://www.pageflakes.com/"&gt;Pageflakes&lt;/a&gt; we tried many ways if we can eliminate XMLHTTP by using &amp;lt;SCRIPT&amp;gt; tags. But we failed to make it work for many scenario. Both inline &amp;lt;SCRIPT&amp;gt; tag and external &amp;lt;SCRIPT&amp;gt; tag fails. It appears that browser cannot parse large amount of JSON and some JSON which has HTML embedded in it. Browser will not raise any error and you will not see the reason what’s wrong. &lt;/p&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=106889" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/javascript/default.aspx">javascript</category></item><item><title>How to fade background and show a dialog box</title><link>http://msmvps.com/blogs/omar/archive/2006/08/02/How-to-fade-background-and-show-a-dialog-box.aspx</link><pubDate>Wed, 02 Aug 2006 14:23:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:106495</guid><dc:creator>omar</dc:creator><slash:comments>11</slash:comments><description>&lt;p&gt;There&amp;#39;s a nice trick we do at Pageflakes whenever we show a
dialog box. We make the background faded so that user&amp;#39;s attention
is dragged to the dialog box and user does not get confused what to
do. Here&amp;#39;s how it looks:&lt;/p&gt;
&lt;img src="http://omar.mvps.org/pics/PFshaded.jpg" alt="" /&gt;
&lt;p&gt;Here&amp;#39;s how it works:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First we create an absolute DIV which is semi-transparent&lt;/li&gt;
&lt;li&gt;Above that DIV, we create another absolutely positioned DIV
which contains the dialog box&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We also need to make sure user cannot click on anything else
outside the DIV area. We do this by eliminating all mouse events on
the semi-transparent DIV.&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s the DIV code:&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New" size="2"&gt;&amp;lt;div id=&amp;quot;blockUI&amp;quot;
class=&amp;quot;translucent&amp;quot; style=&amp;#39;display: none; background-color: gray;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; width: 100%;
height: 100%; position: absolute; left: 0px; top: 0px; z-index:
50000;&amp;quot;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; onclick=&amp;quot;return
false&amp;quot; onmousedown=&amp;quot;return false&amp;quot; onmousemove=&amp;quot;return false&amp;quot;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; onmouseup=&amp;quot;return
false&amp;quot; ondblclick=&amp;quot;return false&amp;quot;&amp;gt;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;amp;nbsp;&amp;lt;/div&amp;gt;
&lt;br /&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;The translucent class is like this:&lt;/p&gt;
&lt;p&gt;.translucent
&lt;br /&gt;{
&lt;br /&gt;filter:alpha(opacity=50);
&lt;br /&gt;-moz-opacity:0.5;
&lt;br /&gt;opacity:0.5;
&lt;br /&gt;}
&lt;br /&gt;
&lt;br /&gt;Update: There was a problem in the translucent class for
which it was not working in FF and OP. It&amp;#39;s fixed.
&lt;br /&gt;&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=106495" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/javascript/default.aspx">javascript</category></item><item><title>MethodQueue : Replace window.setTimeout and reuse timers</title><link>http://msmvps.com/blogs/omar/archive/2006/08/02/methodqueue-replace-window-settimeout-and-reuse-timers.aspx</link><pubDate>Wed, 02 Aug 2006 14:06:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:106489</guid><dc:creator>omar</dc:creator><slash:comments>2</slash:comments><description>&lt;p&gt;We were having problem with inappropriate use of
window.setTimeout in the flakes at Pageflakes. Too many times were
getting registered and some of the flakes were generating
continuous hit to our server from those timed method calls.&lt;/p&gt;
&lt;p&gt;In order to resolve this problem, we replaced all
window.setTimeout calls with a handy class called MethodQueue which
maintains a queue of functions to call and reuses timers for the
same duration.&lt;/p&gt;
&lt;p&gt;Here&amp;#39;re the methods on method queue:&lt;/p&gt;
&lt;p&gt;MethodQueue.add( id, delay, resetTimer, function );
&lt;br /&gt;MethodQueue.remove( id, delay )&lt;/p&gt;
&lt;p&gt;The add method prevents duplicate method being queue in the same
duration. So, you don&amp;#39;t need to:&lt;/p&gt;
&lt;p&gt;1. Store timer ID in a variable
&lt;br /&gt;2. Check if the timer is there, clear if need to reset 3.
Call setTimeout to register the timer.&lt;/p&gt;
&lt;p&gt;Very frequently we write codes like:&lt;/p&gt;
&lt;p&gt;if( !timerID )
&lt;br /&gt;&amp;nbsp;timerID = window.setTimeout( dosomething, duration
);&lt;/p&gt;
&lt;p&gt;and then later on clear the timer using window.clearTimeout(
timerID ); You don&amp;#39;t need to do this when you have MethodQueue.&lt;/p&gt;
&lt;p&gt;This also reuses one timer for multiple callback on the same
delay. So, if 5 flakes want to register a callback on 1000ms delay,
there will be only one timer.&lt;/p&gt;
&lt;p&gt;Sample usage:&lt;/p&gt;
&lt;p&gt;MethodQueue.add( &amp;#39;Myflake.Mycallback&amp;#39;, 1000, true, function() {
.... } );&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s the code for MethodQueue:&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New" size="2"&gt;var MethodQueue =
&lt;br /&gt;{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; delays : [],
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; timerIDs : [],
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; add : function(id, delay, resetIfExist,
func )
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var queue =
MethodQueue.delays[delay]; // get the queue for this delay
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( null == queue
) queue = [];
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( null ==
queue[id] ) // first time registration
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
queue[id] = { id: id, code: func, reset: false }; // register the
function in the delay queue
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
// same id, same delay already exist. If reset defined, then store
the new function and discard previous one
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
if( resetIfExist ) { queue[id] = { id: id, code: func, reset: true
}; }
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
else { return; }
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
MethodQueue.delays[delay] = queue; // register the queue in the
delay
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(
MethodQueue.timerIDs[delay] == null )
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
MethodQueue.timerIDs[delay] = window.setTimeout( function()
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
MethodQueue.execute(delay);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}, delay );
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; },
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; execute : function( delay )
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var delayQueue =
MethodQueue.delays[ delay ];
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for( var key in
delayQueue )
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
var item = delayQueue[key];
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
if( item != null )
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
if( typeof item.code == &amp;quot;function&amp;quot; )
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
if( !item.reset )&amp;nbsp;&amp;nbsp; // if this method was not reset, then
execute it
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
delayQueue[key] = null; // remove this item, incase the code tries
to register again, it will get this key free
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
item.code();&amp;nbsp;&amp;nbsp;&amp;nbsp; // execute the code, note it might
register the timer callback again
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
delete
item.code;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
else
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
item.reset = false;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // find out if
there&amp;#39;s any callback left in the queue.
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // it might happen
that, when a callback was called, it
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // registered in
the same delay queue again
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var
allCallbackCalled = true;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for( var key in
delayQueue )
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
var item = delayQueue[key];
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
if( item != null )
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
if( typeof item.code == &amp;quot;function&amp;quot; )
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
allCallbackCalled = false;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(
allCallbackCalled ) // if all callbacks in the queue fired, we can
remove this queue and timer
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
delete delayQueue;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
MethodQueue.delays[ delay ] = null;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
delete MethodQueue.delays[ delay ];
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
window.clearTimeout( MethodQueue.timerIDs[delay] );
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
MethodQueue.timerIDs[delay] = null;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
delete MethodQueue.timerIDs[delay];
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
// re-register the timer
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
MethodQueue.timerIDs[delay] = window.setTimeout( function()
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
MethodQueue.execute(delay);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}, delay );
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; },
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; exist : function( id, delay )
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var queue =
MethodQueue.delays[delay];
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( null == queue
) queue = [];
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ( null !=
queue[id] );&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; },
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; remove : function( id, delay )
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var queue =
MethodQueue.delays[delay];
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( null == queue
) return;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else queue[id] =
null;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
MethodQueue.delays[delay] = queue;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;br /&gt;}
&lt;br /&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=106489" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/javascript/default.aspx">javascript</category></item><item><title>Browser detection using Javascript</title><link>http://msmvps.com/blogs/omar/archive/2006/08/02/browser-detection-using-javascript.aspx</link><pubDate>Wed, 02 Aug 2006 12:39:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:106483</guid><dc:creator>omar</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;Here&amp;#39;s a short class which helps detecting major browser
types:&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New" size="2"&gt;var Browser = new Object();
&lt;br /&gt;var ua = navigator.userAgent.toLowerCase();
&lt;br /&gt;Browser.isMozilla = (typeof document.implementation !=
&amp;#39;undefined&amp;#39;) &amp;amp;&amp;amp; (typeof
document.implementation.createDocument != &amp;#39;undefined&amp;#39;) &amp;amp;&amp;amp;
(typeof HTMLDocument!=&amp;#39;undefined&amp;#39;);
&lt;br /&gt;Browser.isIE = window.ActiveXObject ? true : false;
&lt;br /&gt;Browser.isFirefox = (ua.indexOf(&amp;quot;firefox&amp;quot;)!=-1);
&lt;br /&gt;Browser.isSafari = (ua.indexOf(&amp;quot;Browser.isSafari&amp;quot;)!=-1);
&lt;br /&gt;Browser.isOpera = (typeof window.opera != &amp;#39;undefined&amp;#39;);
&lt;br /&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=106483" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/javascript/default.aspx">javascript</category></item><item><title>How to load scripts by browser dynamically</title><link>http://msmvps.com/blogs/omar/archive/2006/08/02/how-to-load-scripts-by-browser-dynamically.aspx</link><pubDate>Wed, 02 Aug 2006 12:29:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:106482</guid><dc:creator>omar</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;Here&amp;#39;s a nice handy function for loading external scripts
dynamically using BLOCKED SCRIPT&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New" size="2"&gt;function $addScript( id, src )
&lt;br /&gt;&lt;/font&gt; 
&lt;font face="Courier New" size="2"&gt;{&lt;/font&gt;
&lt;font face="Courier New" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br /&gt;var o = $$(&amp;quot;script&amp;quot;);&amp;nbsp;
&lt;br /&gt;&lt;/font&gt;
&lt;font face="Courier New" size="2"&gt;o.id = id;
&lt;br /&gt;o.type = &amp;quot;text/javascript&amp;quot;;
&lt;br /&gt;o.setAttribute(&amp;quot;src&amp;quot;, src);
&lt;br /&gt;document.getElementsByTagName(&amp;#39;head&amp;#39;)[0].appendChild(o);
&lt;br /&gt;return o;
&lt;br /&gt;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;Just call $addScript( &amp;#39;someid&amp;#39;,
&amp;#39;http://www.pageflakes.com/somescript.js&amp;#39;) and it will load the
script.&lt;/p&gt;
&lt;p&gt;However, if you want to wait for the script to download before
you do something, here&amp;#39;s what you need to do:&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New" size="2"&gt;var oScript = $addScript( &amp;#39;id&amp;#39;,
&amp;#39;http://.....&amp;#39; );&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;
&lt;font size="2"&gt;if( Browser.isIE )
&lt;br /&gt;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br /&gt;&amp;nbsp;
&lt;br /&gt;&amp;nbsp;if (oScript.readyState != &amp;quot;loaded&amp;quot;)
&lt;br /&gt;&amp;nbsp;{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;oScript.onreadystatechange = function(event)
&lt;br /&gt;&amp;nbsp;&amp;nbsp;{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (this.readyState == &amp;quot;loaded&amp;quot;)
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;oScript.onreadystatechange = null;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Script has loaded. Do something.
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&lt;br /&gt;&amp;nbsp;&amp;nbsp;}
&lt;br /&gt;&amp;nbsp;}
&lt;br /&gt;}
&lt;br /&gt;if( Browser.isFirefox )
&lt;br /&gt;{
&lt;br /&gt;&amp;nbsp;if (oScript.readyState != &amp;quot;loaded&amp;quot;)
&lt;br /&gt;&amp;nbsp;{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;oScript.onerror = oScript.onload =
function(event)
&lt;br /&gt;&amp;nbsp;&amp;nbsp;{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;oScript.onreadystatechange = null;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Script has either loaded or failed to
load.
&lt;br /&gt;&amp;nbsp;&amp;nbsp;}
&lt;br /&gt;&amp;nbsp;}
&lt;br /&gt;}&lt;/font&gt;
&lt;br /&gt;
&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;Browser is a helper class which tests for Browser. The idea is,
script object has onload and onerror events on Firefox and in IE it
has one generic onreadystatechange event where you can get the
state of the script object from readyState property.&lt;/p&gt;
&lt;p&gt;This way you can download javascript files and wait until it is
downloaded. This comes handy when you want to use something from
the javascript which you cannot do until the file completely
downloads.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=106482" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/javascript/default.aspx">javascript</category></item></channel></rss>