<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Joshua Stengel</title><link>http://weblogs.asp.net/jstengel/default.aspx</link><description>Everything...Is going...&lt;/br&gt;
To be okay!</description><dc:language>en</dc:language><generator>CommunityServer 2007 SP1 (Build: 20510.895)</generator><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/JoshuaStengel" type="application/rss+xml" /><item><title>Getting paid enough?</title><link>http://feedproxy.google.com/~r/JoshuaStengel/~3/VIOPtM303oo/getting-paid-enough.aspx</link><pubDate>Tue, 07 Apr 2009 18:18:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7033779</guid><dc:creator>jstengel</dc:creator><slash:comments>0</slash:comments><wfw:commentRss>http://weblogs.asp.net/jstengel/rsscomments.aspx?PostID=7033779</wfw:commentRss><comments>http://weblogs.asp.net/jstengel/archive/2009/04/07/getting-paid-enough.aspx#comments</comments><description>&lt;P&gt;30,055 participants contributed to the &lt;A href="http://aneventapart.com/alasurvey2008/"&gt;&lt;FONT color=#0065e2&gt;"A LIST APART" survey&lt;/FONT&gt;&lt;/A&gt; of people who are building the web (developers, designers, etc.).&amp;nbsp; Topics covered include things like, education, compensation, experience, age, ethnicity, vacation days, etc. &lt;/P&gt;
&lt;P&gt;My favorite statistic, 13.8% of us have had a blog or personal site/blog for over a decade.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;What stood out to you?&lt;/P&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7033779" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JoshuaStengel/~4/VIOPtM303oo" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jstengel/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/Developer+Tools/default.aspx">Developer Tools</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/surveys/default.aspx">surveys</category><feedburner:origLink>http://weblogs.asp.net/jstengel/archive/2009/04/07/getting-paid-enough.aspx</feedburner:origLink></item><item><title>Would you like a FREE book?</title><link>http://feedproxy.google.com/~r/JoshuaStengel/~3/wZ4hDfoykFQ/would-you-like-a-free-book.aspx</link><pubDate>Mon, 05 Jan 2009 12:48:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6818153</guid><dc:creator>jstengel</dc:creator><slash:comments>11</slash:comments><wfw:commentRss>http://weblogs.asp.net/jstengel/rsscomments.aspx?PostID=6818153</wfw:commentRss><comments>http://weblogs.asp.net/jstengel/archive/2009/01/05/would-you-like-a-free-book.aspx#comments</comments><description>&lt;P&gt;Help me spend my gift cards wisely and you can keep what I buy. &lt;/P&gt;
&lt;P&gt;You pick them out. I buy them. I read them. I mail them to you--free of charge.&lt;/P&gt;
&lt;P&gt;The rules are:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;The book(s) must be available from &lt;A href="http://borders.com/" mce_href="http://borders.com"&gt;http://borders.com&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;The book can be technical, fiction, audio, non-fiction, sci-fi, whatever, but it needs to be something I haven't read or don't already own. &lt;/LI&gt;
&lt;LI&gt;I will buy the most interesting recommendations first until my gift cards are spent, so sell me on why I should pick your recommendation. &lt;/LI&gt;
&lt;LI&gt;No reference books. &lt;/LI&gt;
&lt;LI&gt;Movies are okay, but picking a good movie that I haven't seen or don't own will be tough. &lt;/LI&gt;
&lt;LI&gt;If I pick your book, I'll email you to get your shipping info.&amp;nbsp; After I read your book, I'll send it to you or someone else on your behalf. &lt;/LI&gt;
&lt;LI&gt;USA delivery only. &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;Here are some things I might be interested in:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Books about successful businesses or business people &lt;/LI&gt;
&lt;LI&gt;Interesting biographies &lt;/LI&gt;
&lt;LI&gt;Comedies &lt;/LI&gt;
&lt;LI&gt;New technical books &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Tip! Get others to vote for your recommendation to improve your odds.&lt;/P&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6818153" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JoshuaStengel/~4/wZ4hDfoykFQ" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jstengel/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/Developer+Tools/default.aspx">Developer Tools</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/Freebies/default.aspx">Freebies</category><feedburner:origLink>http://weblogs.asp.net/jstengel/archive/2009/01/05/would-you-like-a-free-book.aspx</feedburner:origLink></item><item><title>What the heck is the "Microsoft Web Platform Installer?"</title><link>http://feedproxy.google.com/~r/JoshuaStengel/~3/aEVQadHdrFc/what-the-heck-is-the-quot-microsoft-web-platform-installer-quot.aspx</link><pubDate>Thu, 16 Oct 2008 18:00:19 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6683170</guid><dc:creator>jstengel</dc:creator><slash:comments>5</slash:comments><wfw:commentRss>http://weblogs.asp.net/jstengel/rsscomments.aspx?PostID=6683170</wfw:commentRss><comments>http://weblogs.asp.net/jstengel/archive/2008/10/16/what-the-heck-is-the-quot-microsoft-web-platform-installer-quot.aspx#comments</comments><description>&lt;p&gt;&lt;font size="2"&gt;In my TechNet Flash this morning I see this section:&lt;/font&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p style="line-height: 140%; margin: 0in 0in 0pt" class="MsoNormal"&gt;&lt;span style="line-height: 140%; font-family: 'Verdana','sans-serif'; font-size: 8.5pt; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;a href="http://co1piltwb.partners.extranet.microsoft.com/mcoeredir/mcoeredirect.aspx?linkId=10685092&amp;amp;s1=101cf332-3d7c-062b-47df-f39354a3979a"&gt;&lt;strong&gt;&lt;font color="#0033cc" size="2" face="Trebuchet MS"&gt;&lt;em&gt;Download the New Microsoft Web Platform Installer&lt;/em&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;&lt;em&gt;&lt;font face="Trebuchet MS"&gt;&lt;font size="2"&gt; &lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/font&gt;&lt;/font&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family: 'Verdana','sans-serif'; font-size: 8.5pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: en-us; mso-fareast-language: en-us; mso-bidi-language: ar-sa"&gt;&lt;em&gt;&lt;font size="2" face="Trebuchet MS"&gt;The Microsoft Web Platform Installer lets you create a Web platform on your server. The &lt;/font&gt;&lt;/em&gt;&lt;a href="http://co1piltwb.partners.extranet.microsoft.com/mcoeredir/mcoeredirect.aspx?linkId=10685023&amp;amp;s1=101cf332-3d7c-062b-47df-f39354a3979a"&gt;&lt;font color="#0033cc" size="2" face="Trebuchet MS"&gt;&lt;em&gt;Microsoft Web Platform&lt;/em&gt;&lt;/font&gt;&lt;/a&gt;&lt;em&gt;&lt;font size="2" face="Trebuchet MS"&gt; is a reliable, high-performance Web stack that is capable of hosting both ASP.NET and PHP applications on a single server, and can scale to run the largest sites on the Web.&lt;/font&gt;&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;span style="font-family: 'Verdana','sans-serif'; font-size: 8.5pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: en-us; mso-fareast-language: en-us; mso-bidi-language: ar-sa"&gt;&lt;font face="Trebuchet MS"&gt;&lt;font size="2"&gt;&lt;strong&gt;Question #1:&lt;/strong&gt; "What is the Microsoft Web Platform?"&lt;br&gt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;font face="Trebuchet MS"&gt;&lt;font size="2"&gt;&lt;span style="font-family: 'Verdana','sans-serif'; font-size: 8.5pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: en-us; mso-fareast-language: en-us; mso-bidi-language: ar-sa"&gt;&lt;strong&gt;Question #2:&lt;/strong&gt; "Why does it need an installer?"&lt;br&gt;&lt;/span&gt;&lt;span style="font-family: 'Verdana','sans-serif'; font-size: 8.5pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: en-us; mso-fareast-language: en-us; mso-bidi-language: ar-sa"&gt;&lt;strong&gt;Question #3:&lt;/strong&gt; "How is it different that what I currently use to host my websites?"&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family: 'Verdana','sans-serif'; font-size: 8.5pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: en-us; mso-fareast-language: en-us; mso-bidi-language: ar-sa"&gt;&lt;font size="2" face="Trebuchet MS"&gt;So I did some reading...&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family: 'Verdana','sans-serif'; font-size: 8.5pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: en-us; mso-fareast-language: en-us; mso-bidi-language: ar-sa"&gt;&lt;font face="Trebuchet MS"&gt;&lt;font size="2"&gt;&lt;strong&gt;Answer #1:&lt;/strong&gt; The "Microsoft Web Platform" is nothing more than the collection of Microsoft products that might typically be installed on a web server (i.e., IIS, .NET Framework, SQL Server, VisualStudio, etc.).&amp;nbsp; It would be the equivalent of calling MS Office the "Microsoft Office Productivity Platform"--which I think is possibly how they (MS) will be referring to Office "12".&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family: 'Verdana','sans-serif'; font-size: 8.5pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: en-us; mso-fareast-language: en-us; mso-bidi-language: ar-sa"&gt;&lt;font face="Trebuchet MS"&gt;&lt;font size="2"&gt;&lt;strong&gt;Answer #2:&lt;/strong&gt; The "Microsoft Web Platform Installer" is also kind of like the installer that comes with MS Office.&amp;nbsp; It allows you to selected the components you want to install, configure some settings, and carefully read through all the EULAs for the individual components before sitting back and enjoying a nice long progress bar. &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family: 'Verdana','sans-serif'; font-size: 8.5pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: en-us; mso-fareast-language: en-us; mso-bidi-language: ar-sa"&gt;&lt;font face="Trebuchet MS"&gt;&lt;font size="2"&gt;&lt;strong&gt;Answer #3:&lt;/strong&gt; Since you can "roll y'er own" Microsoft Web Platform by simply installing and configuring all the individual components manually, nothing is particularly special about the installer other than it is supposed to make it easier to setup a new web server.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family: 'Verdana','sans-serif'; font-size: 8.5pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: en-us; mso-fareast-language: en-us; mso-bidi-language: ar-sa"&gt;&lt;font size="2" face="Trebuchet MS"&gt;In conclusion...&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;span style="font-family: 'Verdana','sans-serif'; font-size: 8.5pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: en-us; mso-fareast-language: en-us; mso-bidi-language: ar-sa"&gt;&lt;em&gt;&lt;font size="2" face="Trebuchet MS"&gt;Dear Microsoft,&lt;/font&gt;&lt;/em&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family: 'Verdana','sans-serif'; font-size: 8.5pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: en-us; mso-fareast-language: en-us; mso-bidi-language: ar-sa"&gt;&lt;em&gt;&lt;font size="2" face="Trebuchet MS"&gt;Thank you for providing us with fancy-smancy batch file. The fewer progress bars I have to look at the better. &lt;/font&gt;&lt;/em&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family: 'Verdana','sans-serif'; font-size: 8.5pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: en-us; mso-fareast-language: en-us; mso-bidi-language: ar-sa"&gt;&lt;em&gt;&lt;font size="2" face="Trebuchet MS"&gt;However, "Boo...hiss", on the cheesy marketing description. &lt;/font&gt;&lt;/em&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family: 'Verdana','sans-serif'; font-size: 8.5pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: en-us; mso-fareast-language: en-us; mso-bidi-language: ar-sa"&gt;&lt;em&gt;&lt;font size="2" face="Trebuchet MS"&gt;&amp;lt;rollingEyes&amp;gt;&lt;br&gt;&lt;/font&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-family: 'Verdana','sans-serif'; font-size: 8.5pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: en-us; mso-fareast-language: en-us; mso-bidi-language: ar-sa"&gt;&lt;em&gt;&lt;font size="2" face="Trebuchet MS"&gt;The &lt;/font&gt;&lt;/em&gt;&lt;a href="http://co1piltwb.partners.extranet.microsoft.com/mcoeredir/mcoeredirect.aspx?linkId=10685023&amp;amp;s1=101cf332-3d7c-062b-47df-f39354a3979a"&gt;&lt;font color="#0033cc" size="2" face="Trebuchet MS"&gt;&lt;em&gt;Microsoft Web Platform&lt;/em&gt;&lt;/font&gt;&lt;/a&gt;&lt;em&gt;&lt;font size="2" face="Trebuchet MS"&gt; is a reliable, high-performance Web stack that is capable of hosting both ASP.NET and PHP applications on a single server, and can scale to run the largest sites on the Web.&lt;br&gt;&lt;/font&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-family: 'Verdana','sans-serif'; font-size: 8.5pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: en-us; mso-fareast-language: en-us; mso-bidi-language: ar-sa"&gt;&lt;em&gt;&lt;font size="2" face="Trebuchet MS"&gt;&amp;lt;/rollingEyes&amp;gt;&lt;/font&gt;&lt;/em&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family: 'Verdana','sans-serif'; font-size: 8.5pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: en-us; mso-fareast-language: en-us; mso-bidi-language: ar-sa"&gt;&lt;em&gt;&lt;font size="2" face="Trebuchet MS"&gt;Sincerely,&lt;/font&gt;&lt;/em&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-family: 'Verdana','sans-serif'; font-size: 8.5pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: en-us; mso-fareast-language: en-us; mso-bidi-language: ar-sa"&gt;&lt;em&gt;&lt;font size="2" face="Trebuchet MS"&gt;Long-time "Microsoft Web Platform" Assembler&lt;/font&gt;&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;strong&gt;SEE ALSO:&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a target="_blank" href="http://www.microsoft.com/web/channel/products/WebApplicationInstaller.aspx"&gt;Microsoft Web Application Installer&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a target="_blank" href="http://www.microsoft.com/applicationplatform/default.mspx"&gt;Microsoft Application Platform&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6683170" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JoshuaStengel/~4/aEVQadHdrFc" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jstengel/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/Developer+Tools/default.aspx">Developer Tools</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/.NET/default.aspx">.NET</category><feedburner:origLink>http://weblogs.asp.net/jstengel/archive/2008/10/16/what-the-heck-is-the-quot-microsoft-web-platform-installer-quot.aspx</feedburner:origLink></item><item><title>"Just do it!", New Report Tells Government Execs about Web 2.0</title><link>http://feedproxy.google.com/~r/JoshuaStengel/~3/P07SDGRC1bY/quot-just-do-it-quot-new-report-tells-government-execs-about-web-2-0.aspx</link><pubDate>Mon, 18 Aug 2008 10:59:06 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6524667</guid><dc:creator>jstengel</dc:creator><slash:comments>4</slash:comments><wfw:commentRss>http://weblogs.asp.net/jstengel/rsscomments.aspx?PostID=6524667</wfw:commentRss><comments>http://weblogs.asp.net/jstengel/archive/2008/08/18/quot-just-do-it-quot-new-report-tells-government-execs-about-web-2-0.aspx#comments</comments><description>&lt;p&gt;In a &lt;a href="http://www.businessofgovernment.org/publications/grant_reports/details/index.asp?gid=315" target="_blank"&gt;recent report from the IBM Center for the Business of Government&lt;/a&gt;, government executives are strongly urged not to ignore the use of Web 2.0 technologies in their agencies and to re-think the way they serve the public.&lt;/p&gt;  &lt;p&gt;The report is targeted at executive and management-level readers in the U.S. government and provides a nice outline of Web 2.0 technologies, how they are being used, and how the government can and should be leveraging them. Information is conveyed in a non-intimidating but firm manner using terminology and concepts common to the government world.&lt;/p&gt;  &lt;p&gt;In my opinion, lacking from the report seems to be a good strategy for self-motivating the government to adopt Web 2.0 practices.&amp;#160; The government is not motivated by money in the same manner as businesses and therefore needs a realistic strategy for accepting risk as an acceptable part of innovation.&lt;/p&gt;  &lt;p&gt;For much of the government, Evidence-Based Practice (EBP) is substantially the driving force. Unfortunately, acting only on ideas that provide evidence of a sufficient level of effectiveness creates a polarity with innovation. Therefore, what motivation does government have for adopting the always-beta, rapidly changing, and open elements found in Web 2.0?&lt;/p&gt;  &lt;p&gt;Government, especially on a national level, typically has measures in place to determine how well it is serving its purpose. Feedback is the profit/loss performance indicator of the government world (at least in the USA). While politics and power-mongering are also forces in the system, as an ordinary citizen, feedback is how we help the government measure its customer service.&lt;/p&gt;  &lt;p&gt;The next time you use a government service, don't just accept poor service as being &amp;quot;good enough for government work&amp;quot;. If you see improvements in a government service, don't just be surprised and say nothing.&amp;#160; In a democracy, the government must hear from the public before it can respond.&amp;#160; We are not limited to a little booth on election days to talk to the government.&amp;#160; Every government survey, feedback form, comment card, and formal complaint is vote. Don't waste your opportunity to provide the government with the motivation they need to serve the public effectively.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6524667" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JoshuaStengel/~4/P07SDGRC1bY" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jstengel/archive/tags/Social+Networking/default.aspx">Social Networking</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/General+Software+Development/default.aspx">General Software Development</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/Government/default.aspx">Government</category><feedburner:origLink>http://weblogs.asp.net/jstengel/archive/2008/08/18/quot-just-do-it-quot-new-report-tells-government-execs-about-web-2-0.aspx</feedburner:origLink></item><item><title>Avoiding Duplication When Dynamically Adding Scripts and Styles to A Webpage</title><link>http://feedproxy.google.com/~r/JoshuaStengel/~3/aS1qRJPebC4/avoiding-duplication-when-dynamically-adding-scripts-and-styles-to-a-webpage.aspx</link><pubDate>Fri, 01 Aug 2008 21:23:39 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6467989</guid><dc:creator>jstengel</dc:creator><slash:comments>1</slash:comments><wfw:commentRss>http://weblogs.asp.net/jstengel/rsscomments.aspx?PostID=6467989</wfw:commentRss><comments>http://weblogs.asp.net/jstengel/archive/2008/08/01/avoiding-duplication-when-dynamically-adding-scripts-and-styles-to-a-webpage.aspx#comments</comments><description>&lt;p&gt;Recently, I had a project where I was wanting to be able to create a reusable UserControl to display tooltips throughout the application. The control would need to access the jQuery framework, a jQuery plugin, required some inline scripting, and had its own class of styles.&amp;nbsp; Not every page in the application would have tooltips but the pages that did use them would have a lot of them.&lt;/p&gt; &lt;p&gt;If I added all the references to the JavaScript and styles in the Master page, I would be introducing unnecessary bloat for the majority of the application.&amp;nbsp; So, I needed a way to request these resources in the UserControl so they would only be added to the page "on demand".&lt;/p&gt; &lt;p&gt;As you might image, adding them directly into the UserControl would mean that the resources would be requested for EVERY instance of the UserControl on the page.&amp;nbsp; If I used the control 10 times, the jQuery framework would get requested 10 times.&amp;nbsp; Not the most efficient design.&lt;/p&gt; &lt;p&gt;Fortunately, the .NET framework has a nice way of dealing with this by providing a way to dynamically add resources AND check to see if they are already loaded.&amp;nbsp; &lt;/p&gt; &lt;h3&gt;&lt;strong&gt;Dynamically Adding JavaScript&lt;/strong&gt;&lt;/h3&gt; &lt;p&gt;If we just dynamically added links to script files, we would still have the same problem as adding them inline. So, here is a method that checks to see if the script has already been loaded and loads it only if needed:&lt;/p&gt; &lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; height: 91px; background-color: #f4f4f4"&gt; &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Sub&lt;/span&gt; AddScriptFileToPage(&lt;span style="color: #0000ff"&gt;ByVal&lt;/span&gt; ID &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;ByVal&lt;/span&gt; URL &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;If&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Not&lt;/span&gt; Page.ClientScript.IsClientScriptIncludeRegistered(ID) &lt;span style="color: #0000ff"&gt;Then&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;         Page.ClientScript.RegisterClientScriptInclude(ID, URL)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;If&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The one thing to note is that you need to provide some kind of ID for the script.&amp;nbsp; This ID is how .NET checks to see if the script has already been added to the page.&amp;nbsp; Personally, I think that using the filename of the JavaScript helps keep things consistent and kind of makes logical sense but it doesn't really matter as long as it will be unique to that resource.&lt;/p&gt;
&lt;p&gt;If you need to add a block of inline JavaScript, no problem.&amp;nbsp; It's basically the same process with a tiny little tweak:&lt;/p&gt;
&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; height: 100px; background-color: #f4f4f4"&gt;
&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; height: 83px; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Sub&lt;/span&gt; AddScriptBlockToPage(&lt;span style="color: #0000ff"&gt;ByVal&lt;/span&gt; ID &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;ByVal&lt;/span&gt; Script &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;If&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Not&lt;/span&gt; Page.ClientScript.IsClientScriptBlockRegistered(ID) &lt;span style="color: #0000ff"&gt;Then&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;         Page.ClientScript.RegisterClientScriptBlock(Page.&lt;span style="color: #0000ff"&gt;GetType&lt;/span&gt;(), ID, Script, &lt;span style="color: #0000ff"&gt;True&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;If&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Dynamically Adding Stylesheets&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Though not as simple as adding scripts, we can do the same thing for our styles.&amp;nbsp; There are probably a number of way to do this but I chose to check the page header for an existing instance, and add a literal with the link to the stylesheet if it's not found.&lt;/p&gt;
&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; height: 158px; background-color: #f4f4f4"&gt;
&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Sub&lt;/span&gt; AddCSSFileToPage(&lt;span style="color: #0000ff"&gt;ByVal&lt;/span&gt; ID &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;ByVal&lt;/span&gt; URL &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;If&lt;/span&gt; Page.Header.FindControl(ID) &lt;span style="color: #0000ff"&gt;Is&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Then&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; lit &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;New&lt;/span&gt; Literal()&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;         lit.ID = ID&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;         lit.Text = &lt;span style="color: #006080"&gt;"&amp;lt;link rel="&lt;/span&gt;&lt;span style="color: #006080"&gt;"Stylesheet"&lt;/span&gt;&lt;span style="color: #006080"&gt;" type="&lt;/span&gt;&lt;span style="color: #006080"&gt;"text/css"&lt;/span&gt;&lt;span style="color: #006080"&gt;" href="&lt;/span&gt;&lt;span style="color: #006080"&gt;""&lt;/span&gt; &amp;amp; URL &amp;amp; &lt;span style="color: #006080"&gt;""&lt;/span&gt;&lt;span style="color: #006080"&gt;"/&amp;gt;"&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;         Page.Header.Controls.Add(lit)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;If&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Making it Practical&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;You might be wondering why you would go through the trouble of doing all this. Lets make this a bit more useful by creating a class to help us use this functionality efficiently. I created a little ResourceLoader class in my application that looked something like this:&lt;/p&gt;
&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;
&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Namespace&lt;/span&gt; Sample&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;Public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Class&lt;/span&gt; ResourceLoader&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;Public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Shared&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Sub&lt;/span&gt; AddScriptFileToPage(&lt;span style="color: #0000ff"&gt;ByVal&lt;/span&gt; ID &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;ByVal&lt;/span&gt; URL &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; p &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; Page = &lt;span style="color: #0000ff"&gt;CType&lt;/span&gt;(System.Web.HttpContext.Current.Handler, Page)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;If&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Not&lt;/span&gt; p.ClientScript.IsClientScriptIncludeRegistered(ID) &lt;span style="color: #0000ff"&gt;Then&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;                 p.ClientScript.RegisterClientScriptInclude(ID, URL)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;If&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Sub&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;Public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Shared&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Sub&lt;/span&gt; AddScriptBlockToPage(&lt;span style="color: #0000ff"&gt;ByVal&lt;/span&gt; ID &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;ByVal&lt;/span&gt; Script &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; p &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; Page = &lt;span style="color: #0000ff"&gt;CType&lt;/span&gt;(System.Web.HttpContext.Current.Handler, Page)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;If&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Not&lt;/span&gt; p.ClientScript.IsClientScriptBlockRegistered(ID) &lt;span style="color: #0000ff"&gt;Then&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;                 p.ClientScript.RegisterClientScriptBlock(p.&lt;span style="color: #0000ff"&gt;GetType&lt;/span&gt;(), ID, Script, &lt;span style="color: #0000ff"&gt;True&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;If&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Sub&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;Public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Shared&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Sub&lt;/span&gt; AddCSSFileToPage(&lt;span style="color: #0000ff"&gt;ByVal&lt;/span&gt; ID &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;ByVal&lt;/span&gt; URL &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; p &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; Page = &lt;span style="color: #0000ff"&gt;CType&lt;/span&gt;(System.Web.HttpContext.Current.Handler, Page)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; lit &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;New&lt;/span&gt; Literal()&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;             lit.ID = ID&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;             lit.Text = &lt;span style="color: #006080"&gt;"&amp;lt;link rel="&lt;/span&gt;&lt;span style="color: #006080"&gt;"Stylesheet"&lt;/span&gt;&lt;span style="color: #006080"&gt;" type="&lt;/span&gt;&lt;span style="color: #006080"&gt;"text/css"&lt;/span&gt;&lt;span style="color: #006080"&gt;" href="&lt;/span&gt;&lt;span style="color: #006080"&gt;""&lt;/span&gt; &amp;amp; URL &amp;amp; &lt;span style="color: #006080"&gt;""&lt;/span&gt;&lt;span style="color: #006080"&gt;"/&amp;gt;"&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;If&lt;/span&gt; p.Header.FindControl(ID) &lt;span style="color: #0000ff"&gt;Is&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Then&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;                 p.Header.Controls.Add(lit)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;If&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  26:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Sub&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  27:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  28:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Class&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  29:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; Namespace&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Quick Note:&lt;/strong&gt; In a class, you can't directly access the Page.&amp;nbsp; So, note how you can declare a Page and then use it in a class environment.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Now that we have this functionality in our application, we can efficiently request resources without having to worry about duplicating what has already been requested for the page.&amp;nbsp; For example, going back to my tooltip UserControl, here is how I could safely make sure that my resources are being requested but not duplicated:&lt;/p&gt;
&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; height: 122px; background-color: #f4f4f4"&gt;
&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Sub&lt;/span&gt; Page_Load(&lt;span style="color: #0000ff"&gt;ByVal&lt;/span&gt; sender &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Object&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;ByVal&lt;/span&gt; e &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; System.EventArgs) &lt;span style="color: #0000ff"&gt;Handles&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Me&lt;/span&gt;.Load&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;    Sample.ResourceLoader.AddScriptFileToPage(&lt;span style="color: #006080"&gt;"jQuery.js"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"Script/jQuery.js"&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;    Sample.ResourceLoader.AddScriptFileToPage(&lt;span style="color: #006080"&gt;"jQuery.ClueTip.js"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"Scripts/jQuery.ClueTip.js"&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;    Sample.ResourceLoader.AddScriptBlockToPage(&lt;span style="color: #006080"&gt;"Tooltip.ascx"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"$(document).ready(function() {$('a.Tooltip').cluetip({splitTitle: '|'},{cursor: 'pointer'});});)"&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;    Sample.ResourceLoader.AddCSSFileToPage(&lt;span style="color: #006080"&gt;"jQuery.ClueTip.css"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"CSS/jQuery.ClueTip.css"&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Notice that every instance of the control will make sure that the jQuery framework, the plugin, the inline script, and the custom styles are loaded but, thanks to our handy-dandy ResourceLoader class, no duplication will take place.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Final Thoughts&lt;/h3&gt;
&lt;p&gt;Even though we aren't duplicating resource requests, we are adding more objects to the page and this potentially introduces latency issues.&amp;nbsp; It also introduces the opportunity to look at how we might extend this technique to combine everything before page makes the request.&amp;nbsp; I've been reading a few ideas on how this might done and, if I end up with a good solution, I'll write a follow up.&lt;/p&gt;
&lt;p&gt;If you have any ideas, comments, criticisms, or suggestions please share.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6467989" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JoshuaStengel/~4/aS1qRJPebC4" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jstengel/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/UI/default.aspx">UI</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/.NET/default.aspx">.NET</category><feedburner:origLink>http://weblogs.asp.net/jstengel/archive/2008/08/01/avoiding-duplication-when-dynamically-adding-scripts-and-styles-to-a-webpage.aspx</feedburner:origLink></item><item><title>UserAgent Fix for the RSSToolkit 2.0.0.0</title><link>http://feedproxy.google.com/~r/JoshuaStengel/~3/HNtj9bYGes8/useragent-fix-for-the-rsstoolkit-2-0-0-0.aspx</link><pubDate>Thu, 24 Jul 2008 19:16:02 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6440064</guid><dc:creator>jstengel</dc:creator><slash:comments>8</slash:comments><wfw:commentRss>http://weblogs.asp.net/jstengel/rsscomments.aspx?PostID=6440064</wfw:commentRss><comments>http://weblogs.asp.net/jstengel/archive/2008/07/24/useragent-fix-for-the-rsstoolkit-2-0-0-0.aspx#comments</comments><description>&lt;p&gt;I frequently use the RSSToolkit to consume and display RSS feeds from other blogs.&amp;#160; Recently, I've noticed problems with the RSSToolkit not being able to display feed from some external sources.&amp;#160; In particular, I've been having trouble consuming feeds from external blogs like Blogspot and Feedburner.&amp;#160; The symptoms appeared over the past month or two and included the disappearance of consumed blogs and new blog posts.&lt;/p&gt;  &lt;p&gt;After some digging, I found &lt;a href="http://blog.obishawn.com/2008/06/feedburner-404-error.html"&gt;this entry on Obishan's blog&lt;/a&gt; that gave me a clue. &lt;a href="http://web-sniffer.net/?url=http%3A%2F%2Ffeeds.feedburner.com%2FJoshuaStengel&amp;amp;submit=Submit&amp;amp;http=1.1&amp;amp;gzip=yes&amp;amp;type=GET&amp;amp;uak=8"&gt;Using Web-Sniffer&lt;/a&gt;, I was able to verify that if no UserAgent was provided for the request, the request was redirected (302).&amp;#160; This redirection seems to the source of my problems with the RSSToolkit and &lt;a href="http://www.codeplex.com/WorkItem/View.aspx?ProjectName=ASPNETRSSToolkit&amp;amp;WorkItemId=13291"&gt;I'm not the only one&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;This wasn't &lt;a href="http://weblogs.asp.net/jstengel/archive/2008/01/26/a-small-fix-for-rsstoolkit-2-0-0-0.aspx"&gt;my first crack at fixing an issue with the RSSToolkit&lt;/a&gt;, so I spent some time tracking done how to fix this issue. Basically, I needed to find out where the RSSToolkit was actually requesting the RSS and find out how to modify the request so that it included a UserAgent. In my fix I am hardcoding in the UserAgent.&amp;#160; Ideally, this would be set through a property in the control.&lt;/p&gt;  &lt;h1&gt;The Fix&lt;/h1&gt;  &lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; &lt;a href="http://www.codeplex.com/ASPNETRSSToolkit/Release/ProjectReleases.aspx?ReleaseId=3674"&gt;Download the Source&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Update the Code&lt;/p&gt;  &lt;p&gt;Open RSSToolkit &amp;gt; RSS &amp;gt; DownloadManager.cs and replace the DownloadFeedDom() with the following:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; CacheInfo DownLoadFeedDom(&lt;span class="kwrd"&gt;string&lt;/span&gt; url)
        {
            &lt;span class="rem"&gt;//// look for disk cache first&lt;/span&gt;
            CacheInfo dom = TryLoadFromDisk(url);

            &lt;span class="kwrd"&gt;if&lt;/span&gt; (CacheReadable(dom))
            {
                &lt;span class="kwrd"&gt;return&lt;/span&gt; dom;
            }

            &lt;span class="kwrd"&gt;string&lt;/span&gt; ttlString = &lt;span class="kwrd"&gt;null&lt;/span&gt;;

            &lt;span class="rem"&gt;//MODIFICATION: Some RSS sources like Facebook and Feedburner look&lt;/span&gt;
            &lt;span class="rem"&gt;//for a UserAgent (browser/OS information)&lt;/span&gt;

            String userAgent = &lt;span class="str"&gt;@&amp;quot;Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)&amp;quot;&lt;/span&gt;;
            HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(url);
            httpRequest.UserAgent = userAgent;
            HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();
            XmlDocument doc = &lt;span class="kwrd"&gt;new&lt;/span&gt; XmlDocument();
            doc.Load(httpResponse.GetResponseStream());
            httpResponse.Close();
            doc.Save(Console.Out);

            &lt;span class="rem"&gt;//END OF MODIFICATION&lt;/span&gt;

            &lt;span class="kwrd"&gt;if&lt;/span&gt; (doc.SelectSingleNode(&lt;span class="str"&gt;&amp;quot;/rss/channel/ttl&amp;quot;&lt;/span&gt;) != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
            {
                ttlString = doc.SelectSingleNode(&lt;span class="str"&gt;&amp;quot;/rss/channel/ttl&amp;quot;&lt;/span&gt;).Value;
            }

            &lt;span class="rem"&gt;//// compute expiry&lt;/span&gt;
            &lt;span class="kwrd"&gt;int&lt;/span&gt; ttlMinutes = GetTtlFromString(ttlString, _defaultTtlMinutes);
            DateTime utcExpiry = DateTime.UtcNow.AddMinutes(ttlMinutes);

            &lt;span class="rem"&gt;//// save to disk&lt;/span&gt;
            &lt;span class="kwrd"&gt;return&lt;/span&gt; TrySaveToDisk(doc, url, utcExpiry);
        }&lt;/pre&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Rebuild the Project and use the new RssToolkit.dll&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(Optional) Step 4:&lt;/strong&gt; Download my copies.&amp;#160; My versions also include &lt;a href="http://weblogs.asp.net/jstengel/archive/2008/01/26/a-small-fix-for-rsstoolkit-2-0-0-0.aspx"&gt;my fix for Atom feeds&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href="http://weblogs.asp.net/blogs/jstengel/Source%20-%20RssToolkit%202.0.0.2.zip"&gt;RssToolkit 2.0.0.2: Project with source&lt;/a&gt;&lt;/li&gt;

    &lt;li&gt;&lt;a href="http://weblogs.asp.net/blogs/jstengel/DLL%20-%20RssToolkit%202.0.0.2%20.zip"&gt;RssToolkit 2.0.0.2: Compiled DLL&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/ul&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6440064" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JoshuaStengel/~4/HNtj9bYGes8" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jstengel/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/RSS/default.aspx">RSS</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/Developer+Tools/default.aspx">Developer Tools</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/.NET/default.aspx">.NET</category><feedburner:origLink>http://weblogs.asp.net/jstengel/archive/2008/07/24/useragent-fix-for-the-rsstoolkit-2-0-0-0.aspx</feedburner:origLink></item><item><title>Sorry, Vista...It's not you, it's me.</title><link>http://feedproxy.google.com/~r/JoshuaStengel/~3/A0dXKf80ETw/sorry-vista-it-s-not-you-it-s-me.aspx</link><pubDate>Mon, 09 Jun 2008 19:26:41 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6262955</guid><dc:creator>jstengel</dc:creator><slash:comments>2</slash:comments><wfw:commentRss>http://weblogs.asp.net/jstengel/rsscomments.aspx?PostID=6262955</wfw:commentRss><comments>http://weblogs.asp.net/jstengel/archive/2008/06/09/sorry-vista-it-s-not-you-it-s-me.aspx#comments</comments><description>&lt;p&gt;I bought a discount PC from a highly reputable company (okay, it was Woot) a couple of months ago to replace my aging PC at home.&amp;nbsp; I come from a hardware background so I'm more apt to put up with crappier parts in exchange for a good deal.&amp;nbsp; However, when "crappy" meets "incompatible", I've got problems.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Problem #1:&lt;/strong&gt; &lt;/p&gt; &lt;p&gt;My new PC came with a dual-head PCIe video card.&amp;nbsp; Cool, I thought.&amp;nbsp; I can just slap my extra PCI video card in the free slot and my 3-monitor setup will just as good as under my older Windows XP machine with the single onboard AGP and added dual-head PCI setup. WRONG! WRONG! WRONG!&lt;/p&gt; &lt;p&gt;Windows Vista is picky about the co-interminglicizing of video cards when using PCI Express.&amp;nbsp; Long story short, don't try it.&amp;nbsp; Either use the same video cards from the same vendor in the same adapter friendly, or prepare for a battle you will lose.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Problem #2&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;So, it won't work under Vista. Okay, I need 3 monitors more than a pretty-but-bitchy OS (yeah, you know what I mean).&amp;nbsp; I'll just go back to XP on my new machine.&amp;nbsp; NOPE!&lt;/p&gt; &lt;p&gt;Turns out XP doesn't like the chipset in my motherboard and blue screens during setup.&amp;nbsp; Long story short, XP setup does not have the necessary mass storage drivers to get through the setup.&amp;nbsp; Why not load the drivers on a disk and use the F6 method? Well, this system does not have floppy disk support.&amp;nbsp; So, I thought I would be clever and try to slipstream the drivers into a custom XP setup disk.&amp;nbsp; It may have been clever, but it still didn't work.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Bottom Line&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;I'm pretty much hosed.&amp;nbsp; It's back to my old system that, even though it's not as wizz-diddly as the new one, is still more functional that my new Vista PC that won't run XP.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Moral of the Story&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;I don't know that there is much to learn here.&amp;nbsp; I guess for a few hundred bucks (cost of the new PC) I learned a lot about about Vista's support for multiple graphics adapters and also how to use slipstreaming to create custom OS setup disks.&amp;nbsp; I also leaned to love the word "slipstream" and plan to use it as often as possible.&lt;/p&gt; &lt;p&gt;Anyone else want a learning experience?&amp;nbsp; &lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;strong&gt;&lt;em&gt;For Sale:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;One (1) slightly used PC. &lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;strong&gt;Bonus Material&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Did you know that "slipstream" can also be &lt;a href="http://www.combat.ws/S4/MILTERMS/PARATERM.HTM" target="_blank"&gt;defined&lt;/a&gt; as "the "burble" of turbulence generated by an object passing through air or space, as the airstream or backwash (wash) around an aircraft from its propulsion?" Awesome! In true tech-style lingo, I give you "BUTT", the newest buzzword for the latest development process designed to intimidate and impress those who are just too stupid to grasp the advantages of having more BUTT action in their environment.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;br&gt;&lt;strong&gt;"Burble"-Up Transfer of Technology (BUTT)&lt;/strong&gt;&lt;br&gt;&lt;em&gt; The process of slipstreaming lessons learned from past projects into future projects.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6262955" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JoshuaStengel/~4/A0dXKf80ETw" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jstengel/archive/tags/General+Software+Development/default.aspx">General Software Development</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/Humor+_2800_maybe_2900_/default.aspx">Humor (maybe)</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/Vista/default.aspx">Vista</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/Hardware/default.aspx">Hardware</category><feedburner:origLink>http://weblogs.asp.net/jstengel/archive/2008/06/09/sorry-vista-it-s-not-you-it-s-me.aspx</feedburner:origLink></item><item><title>Problem: Existing users will try to create new accounts</title><link>http://feedproxy.google.com/~r/JoshuaStengel/~3/wgKnVvo-dE8/problem-existing-users-try-to-create-new-accounts.aspx</link><pubDate>Mon, 02 Jun 2008 20:26:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6242978</guid><dc:creator>jstengel</dc:creator><slash:comments>2</slash:comments><wfw:commentRss>http://weblogs.asp.net/jstengel/rsscomments.aspx?PostID=6242978</wfw:commentRss><comments>http://weblogs.asp.net/jstengel/archive/2008/06/02/problem-existing-users-try-to-create-new-accounts.aspx#comments</comments><description>&lt;P&gt;A typical web-based authentication system will have two options--Sign In (a path for existing users) and Register (a path for new users).&amp;nbsp; Potential problems for users arise when they don't know if they have an account, or they have tried to sign in unsuccessfully and decide to try to create another account.&amp;nbsp; Typically, when an existing user tries to create another account, they get an error message or some instructions for recovering their information.&amp;nbsp; The user may or may not bother with the effort. &lt;/P&gt;
&lt;P&gt;Consider this...How likely is it that an existing user, when trying to create a new account, will use the same or similar information as when they first created their account? Now, imagine if you simply&lt;STRONG&gt; allowed the registration form to also act as a sign in form&lt;/STRONG&gt;. Or, make the sign in form step one of the registration process.&amp;nbsp; It should be easy attempt an authentication using the information in a registration form and bypass the actual creation of a new account if an existing account is found, so why not do it?&lt;/P&gt;
&lt;P&gt;I know what you're thinking...what if the user *doesn't* enter the same information.&amp;nbsp; For example, what if the username is different but the provided email address matches an existing account.&amp;nbsp; Create a trigger that starts the necessary account recovery process and notify the user what is happening? &lt;/P&gt;
&lt;P&gt;By allowing authentication to happen in a registration form you can potentially:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Unobtrusively sign in existing users who didn't know they had an account.&lt;/LI&gt;
&lt;LI&gt;Save user frustration by triggering the login recovery process for them using information they already provided.&lt;/LI&gt;
&lt;LI&gt;Prevent abandonment by users not willing to make the traditional effort.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;What do you think?&amp;nbsp; Anyone doing this or considering this approach? Why/why not?&lt;/P&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6242978" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JoshuaStengel/~4/wgKnVvo-dE8" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jstengel/archive/tags/UI/default.aspx">UI</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/Social+Networking/default.aspx">Social Networking</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/General+Software+Development/default.aspx">General Software Development</category><feedburner:origLink>http://weblogs.asp.net/jstengel/archive/2008/06/02/problem-existing-users-try-to-create-new-accounts.aspx</feedburner:origLink></item><item><title>Un-sucking the Radio Button</title><link>http://feedproxy.google.com/~r/JoshuaStengel/~3/lxgG3tgo5vo/un-sucking-the-radio-button.aspx</link><pubDate>Mon, 19 May 2008 21:53:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6201945</guid><dc:creator>jstengel</dc:creator><slash:comments>4</slash:comments><wfw:commentRss>http://weblogs.asp.net/jstengel/rsscomments.aspx?PostID=6201945</wfw:commentRss><comments>http://weblogs.asp.net/jstengel/archive/2008/05/19/un-sucking-the-radio-button.aspx#comments</comments><description>&lt;P&gt;I swear radio buttons pucker up the closer my mouse gets to them.&amp;nbsp; Aside from the lack of good CSS options for radio buttons, they demand a certain level of commitment from the user. Unlike our promiscuous friend the checkbox, once you manage to jab the tip of your mouse into the pinhole of a radio button that's it. There's no unpoking that hole. Sure, you might be able to move it around in a group of radio buttons but, you're pretty much committed to an option.&lt;/P&gt;
&lt;P&gt;So, to un-suck the radio button, we need:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Free will.&lt;/STRONG&gt;&amp;nbsp; The users should be able to unselect their answer. 
&lt;LI&gt;&lt;STRONG&gt;Mutual exclusiveness.&lt;/STRONG&gt;&amp;nbsp; If we don't have this, we've got nothing but checkboxes.&amp;nbsp; Only one answer can be selected. 
&lt;LI&gt;&lt;STRONG&gt;Potential beauty:&lt;/STRONG&gt; Why be limited to puckered pinholes if we can pretty it up a bit.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;By creating a little mash-up using some controls from the &lt;A href="http://www.asp.net/AJAX/AjaxControlToolkit/" target=_blank mce_href="http://www.asp.net/AJAX/AjaxControlToolkit/"&gt;&lt;STRONG&gt;AJAX Control Toolkit&lt;/STRONG&gt;&lt;/A&gt;, maybe we can make something a little better than the standard HTML inputs.&amp;nbsp; Let's be honest.&amp;nbsp; This is not a lightweight approach.&amp;nbsp; I'm not going to tell you what to do but, I would only do this only where the UI &lt;EM&gt;bang&lt;/EM&gt; is worth the page load &lt;EM&gt;buck&lt;/EM&gt;.&lt;IMG style="MARGIN: 10px" alt="Don't click on this.  It's just a screenshot." src="http://weblogs.asp.net/blogs/jstengel/RadioButtonExample.JPG" align=right mce_src="http://weblogs.asp.net/blogs/jstengel/RadioButtonExample.JPG"&gt;&lt;/P&gt;
&lt;P&gt;Let's tackle mutual exclusiveness first. In case you aren't familiar with the terminology, mutual exclusiveness is the idea that by selecting one item, you exclude yourself from selecting something else. For example, if you chose life, you cannot choose death.&amp;nbsp; To chose death you must not choose life.&amp;nbsp; So, how do we assure a monogamous answer using a bunch of promiscuous checkboxes? For this task, we'll need a chaperone and, fortunately, the Toolkit also has a little thing called a &lt;A href="http://www.asp.net/AJAX/AjaxControlToolkit/Samples/MutuallyExclusiveCheckBox/MutuallyExclusiveCheckBox.aspx" target=_blank mce_href="http://www.asp.net/AJAX/AjaxControlToolkit/Samples/MutuallyExclusiveCheckBox/MutuallyExclusiveCheckBox.aspx"&gt;&lt;STRONG&gt;MutuallyExclusiveCheckBoxExtender&lt;/STRONG&gt;&lt;/A&gt;--just rolls off the tongue doesn't it.&amp;nbsp;&amp;nbsp; This control can make check boxes behave like radio buttons! Yes! No, wait...radio buttons suck, right? A square pinhole is really not that much more fun to poke than a round one, is it?&lt;/P&gt;
&lt;P&gt;Enter the &lt;A href="http://www.asp.net/AJAX/AjaxControlToolkit/Samples/ToggleButton/ToggleButton.aspx" target=_blank mce_href="http://www.asp.net/AJAX/AjaxControlToolkit/Samples/ToggleButton/ToggleButton.aspx"&gt;&lt;STRONG&gt;ToggleButtonExtender&lt;/STRONG&gt;&lt;/A&gt;.&amp;nbsp; This AJAX Control Toolkit control allows you override the default HTML checkbox with your own custom images.&amp;nbsp; Sweet! If we use this with some checkboxes, we have achieved "free will" and "potential beauty" in one shot. &lt;/P&gt;
&lt;P&gt;By combining a couple of ready-made tools, we can un-suck the radio button by using checkboxes.&amp;nbsp; Hmmm...Maybe I should have titled the article "Checkbox Performance-Enhancing Controls". It doesn't really matter.&amp;nbsp; The goal is to create a better user interface for a task and that's what un-sucking is all about.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;H3&gt;&lt;STRONG&gt;&lt;/STRONG&gt;&lt;/H3&gt;
&lt;H3&gt;&lt;A href="http://weblogs.asp.net/blogs/jstengel/RadioButtonsSuck.zip" target=_blank mce_href="http://weblogs.asp.net/blogs/jstengel/RadioButtonsSuck.zip"&gt;&lt;STRONG&gt;Download the Example&lt;/STRONG&gt;&lt;/A&gt;&lt;/H3&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;EM&gt;&lt;/EM&gt;&lt;/STRONG&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;EM&gt;Reality Check!&lt;/EM&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Why NOT to do this:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;The complexity and page size increases exponentially the more options you add so, use wisely. 
&lt;LI&gt;You are a Javascript wizard and don't want to add the Toolkit's baggage. 
&lt;LI&gt;Getting the selected value for the pseudo-RadioButtonList and validation is trickier. So what? You're a great programmer and can handle it, right? 
&lt;LI&gt;It makes it easier for users to see what is selected and not selected.&amp;nbsp; So, if you rely on users not seeing which puckered pinhole they may or may not have selected, don't do this.&lt;/LI&gt;&lt;/UL&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6201945" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JoshuaStengel/~4/lxgG3tgo5vo" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jstengel/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/UI/default.aspx">UI</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/AJAX.NET/default.aspx">AJAX.NET</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/AJAX.NET+Toolkit/default.aspx">AJAX.NET Toolkit</category><feedburner:origLink>http://weblogs.asp.net/jstengel/archive/2008/05/19/un-sucking-the-radio-button.aspx</feedburner:origLink></item><item><title>Flash/AJAX File Upload w/ Progress Server Control</title><link>http://feedproxy.google.com/~r/JoshuaStengel/~3/CSXHTbXwvxc/flash-file-upload-server-control.aspx</link><pubDate>Fri, 25 Apr 2008 22:28:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6130647</guid><dc:creator>jstengel</dc:creator><slash:comments>37</slash:comments><wfw:commentRss>http://weblogs.asp.net/jstengel/rsscomments.aspx?PostID=6130647</wfw:commentRss><comments>http://weblogs.asp.net/jstengel/archive/2008/04/25/flash-file-upload-server-control.aspx#comments</comments><description>&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;Editor Note: This control &lt;STRONG&gt;does not support the most recent release of Adobe Flash&lt;/STRONG&gt;.&amp;nbsp; Certain security updates from that release prevent the control from working.&amp;nbsp;&amp;nbsp;Since the release of this control, others have released similar controls that are compatible and I would encourage you to explore those options.&lt;/EM&gt;&amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Recently, I &lt;A href="http://weblogs.asp.net/jstengel/archive/2008/02/22/uploading-files-multiple-files-progress-bar-no-postback.aspx" target=_blank mce_href="http://weblogs.asp.net/jstengel/archive/2008/02/22/uploading-files-multiple-files-progress-bar-no-postback.aspx"&gt;blogged about my favorite file upload technique for web applications&lt;/A&gt;--the free flash/JavaScript-based &lt;A href="http://swfupload.org/" target=_blank mce_href="http://swfupload.org/"&gt;SWFUpload&lt;/A&gt;.&amp;nbsp; While this library is not the perfect solution for all circumstances, it certainly provides a very nice user experience and is worth seeing if it matches your project's requirements.&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://weblogs.asp.net/blogs/jstengel/FlashUpload.JPG" align=right mce_src="http://weblogs.asp.net/blogs/jstengel/FlashUpload.JPG"&gt;I have a project I'm working on that needs a graceful file upload process. The environment is compatible with the flash/JavaScript requirements so I made myself a .NET control for the library.&amp;nbsp; The control contains all the necessary JavaScript and you can set the properties (allowed file types, file size, etc.) just like a normal control so you don't have to mess with any of the scripting.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;The features of this control include:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Multiple file upload (queuing)&lt;/LI&gt;
&lt;LI&gt;Upload progress indicator&lt;/LI&gt;
&lt;LI&gt;Ability to cancel queued files&lt;/LI&gt;
&lt;LI&gt;NO visible PostBack (uses AJAX)&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;For those of you who may be wondering if you just stumbled onto the the "holy grail" of file uploads here, hold y'er horses...&lt;/P&gt;
&lt;P&gt;This is my first customer server control ever. I'd never made one before and this was my "learning project".&amp;nbsp; It's &lt;STRIKE&gt;probably&lt;/STRIKE&gt; not a highly tested and production-ready control. That said, you have the source and it's not that complicated so maybe you can customize it or clean it up if necessary. I would like to know what you think--good or bad, so let me know if you find problems or have some ideas to share.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://weblogs.asp.net/blogs/jstengel/FlashUpload.zip" target=_blank mce_href="http://weblogs.asp.net/blogs/jstengel/FlashUpload.zip"&gt;&lt;B&gt;Download the Project&lt;/B&gt;&lt;/A&gt;&lt;B&gt; (Instructions, Documentation, Source, and Sample Site)&lt;/B&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6130647" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JoshuaStengel/~4/CSXHTbXwvxc" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jstengel/archive/tags/AJAX/default.aspx">AJAX</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/UI/default.aspx">UI</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/Developer+Tools/default.aspx">Developer Tools</category><feedburner:origLink>http://weblogs.asp.net/jstengel/archive/2008/04/25/flash-file-upload-server-control.aspx</feedburner:origLink></item><item><title>Multiple Monitor Productivity Research</title><link>http://feedproxy.google.com/~r/JoshuaStengel/~3/fZXprkqVGZY/multiple-monitor-productivity-research.aspx</link><pubDate>Tue, 15 Apr 2008 19:44:49 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6102437</guid><dc:creator>jstengel</dc:creator><slash:comments>2</slash:comments><wfw:commentRss>http://weblogs.asp.net/jstengel/rsscomments.aspx?PostID=6102437</wfw:commentRss><comments>http://weblogs.asp.net/jstengel/archive/2008/04/15/multiple-monitor-productivity-research.aspx#comments</comments><description>&lt;p&gt;I love multiple monitors.&amp;nbsp; I made everyone at work start using multiple monitors last year. At first they were afraid...they were petrified...but now they don't like working at home if they only have one monitor.&amp;nbsp; If you're looking to justify multiple monitors in your organization, here's a report outlining some productivity research regarding monitor size, aspect ratio, and multiple displays. &lt;/p&gt; &lt;p&gt;Okay, so don't be surprised that display company (NEC) found that larger and more displays improves productivity, but it would appear there is a limit to productivity gains. What's your optimal layout?&amp;nbsp; Check out the report and see for yourself:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://www.necdisplay.com/gowide/NEC_Productivity_Study_0208.pdf" target="_blank"&gt;&lt;strong&gt;Productivity Research: A comparison of Single and Dual Traditional Aspect Displays with a Widescreen Display over Productivity&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;On a related note...Here's a gotcha I banged my head into with Vista and multiple monitors...&lt;br&gt;&lt;img src="http://img.microsoft.com/whdc/images/device/MultimonVista.jpg"&gt; &lt;/p&gt; &lt;p&gt;I recently upgraded my home/office PC.&amp;nbsp; My old system had three monitors under Windows XP and ran great.&amp;nbsp; I used a nVidia AGP card and added an ATI dual-video PCI card to create my surround video.&amp;nbsp; &lt;/p&gt; &lt;p&gt;Enter crotchety ol' Vista with it's fancy-smancy new way of handling multiple graphics cards...&amp;nbsp; Up until now, I've been pretty happy with Vista but this just chaps my hide. If you are planning to use more than two monitors with Vista, you need to &lt;strong&gt;&lt;a href="http://www.microsoft.com/whdc/device/display/multimonVista.mspx" target="_blank"&gt;read this article first&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6102437" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JoshuaStengel/~4/fZXprkqVGZY" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jstengel/archive/tags/General+Software+Development/default.aspx">General Software Development</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/Multimedia/default.aspx">Multimedia</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/Developer+Tools/default.aspx">Developer Tools</category><feedburner:origLink>http://weblogs.asp.net/jstengel/archive/2008/04/15/multiple-monitor-productivity-research.aspx</feedburner:origLink></item><item><title>What happened during my Vista SP1 installation...</title><link>http://feedproxy.google.com/~r/JoshuaStengel/~3/b4m_EE-1tJc/what-happened-during-my-vista-sp1-installation.aspx</link><pubDate>Wed, 19 Mar 2008 21:20:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:5999659</guid><dc:creator>jstengel</dc:creator><slash:comments>3</slash:comments><wfw:commentRss>http://weblogs.asp.net/jstengel/rsscomments.aspx?PostID=5999659</wfw:commentRss><comments>http://weblogs.asp.net/jstengel/archive/2008/03/19/what-happened-during-my-vista-sp1-installation.aspx#comments</comments><description>&lt;P&gt;It all started with my upgrade to VS 2008.&amp;nbsp; I've been using the trial version and only had 3 days left...time to do the deed.&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;IMPORTANT SIDE NOTE: If you are using the trial version, you don't need to do a full uninstall/reinstall.&amp;nbsp; I saw this option the very second I clicked the "uninstall" button.&amp;nbsp; That cost me an hour and a half.&amp;nbsp; Live and learn.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;Back to the story...at the end of the Visual Studio upgrade I got the option to check for updates which I always do.&amp;nbsp; I am reckless with updates and proud of it.&amp;nbsp; I seem to be addicted to see what's going to happen. Will it work? Will it fail? If it fails, will it be spectacular?&amp;nbsp; OMG, what have I done!...It's so exciting.&lt;/P&gt;
&lt;P&gt;For the most part the installation was quite uneventful and I spent most of it daydreaming about my vacation next week.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Then comes the REBOOT!&amp;nbsp; This is the best part of any major update.&amp;nbsp; This is where it can go really really bad, really really fast.&amp;nbsp; I love this part.&lt;/P&gt;
&lt;P&gt;System loads.&amp;nbsp; It pauses before the login screen to install the final 3 parts of Service Pack 1. In big bold letters is the warning, "Do not turn your computer off".&amp;nbsp; I'm starting to sweat and my pulse races as it finishes part 1 and moves to part 2 (like I should care what part it's on--but I do!).&lt;/P&gt;
&lt;P&gt;Part 2 is almost done then...BAMMMM! It's the final episode of Sopranos!&lt;/P&gt;
&lt;P&gt;My screens goes black.&amp;nbsp; The only thing displayed in all three monitors is a cryptic message only a machine could produce.&lt;/P&gt;
&lt;P&gt;"!! 0xC00000 !! 255/73694 (_000000000000000.cfg-ms)"&lt;/P&gt;
&lt;P&gt;I knew the exclamation points could only mean something tremendous had happened.&amp;nbsp; Clearly, to tremendous to put into words. &lt;/P&gt;
&lt;P&gt;I sit there, trembling.&amp;nbsp; I wonder, "Is it dead? Should I leave it and just go home? Should I turn the computer off? No, it said not to. Computers know best, right?"&lt;/P&gt;
&lt;P&gt;My hand shook as I held in the power button. Not from fear--from excitement!&amp;nbsp; It's been a long time since I've had this much fun with an update.&lt;/P&gt;
&lt;P&gt;I held my breath as it began to restart. My heart was pounding.&amp;nbsp; I'm given a choice "Repair Windows Startup" or "Start Windows Normally".&lt;/P&gt;
&lt;P&gt;What's the logical choice?&amp;nbsp; "Repair", you say?&amp;nbsp; As I selected "Start Windows Normally" (honestly, why wouldn't I want it to start anything but "normally"), I sat frozen, hoping it would be okay but at the same time hoping for some kind of explosion.&lt;/P&gt;
&lt;P&gt;The update finished normally, and my machine seems none the worse for wear.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Now, isn't there an IE8 Beta out there somewhere...&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://technet.microsoft.com/en-us/windowsvista/bb738089.aspx" target=_blank mce_href="http://technet.microsoft.com/en-us/windowsvista/bb738089.aspx"&gt;Vista SP1&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://www.microsoft.com/windows/products/winfamily/ie/ie8/default.mspx" target=_blank mce_href="http://www.microsoft.com/windows/products/winfamily/ie/ie8/default.mspx"&gt;IE8 Beta&lt;/A&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=5999659" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JoshuaStengel/~4/b4m_EE-1tJc" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jstengel/archive/tags/Vista/default.aspx">Vista</category><feedburner:origLink>http://weblogs.asp.net/jstengel/archive/2008/03/19/what-happened-during-my-vista-sp1-installation.aspx</feedburner:origLink></item><item><title>Cool Timeline API</title><link>http://feedproxy.google.com/~r/JoshuaStengel/~3/bP6TwjQPklg/cool-timeline-api.aspx</link><pubDate>Mon, 17 Mar 2008 19:25:07 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:5988874</guid><dc:creator>jstengel</dc:creator><slash:comments>3</slash:comments><wfw:commentRss>http://weblogs.asp.net/jstengel/rsscomments.aspx?PostID=5988874</wfw:commentRss><comments>http://weblogs.asp.net/jstengel/archive/2008/03/17/cool-timeline-api.aspx#comments</comments><description>&lt;p&gt;I recently happened upon this &lt;a href="http://simile.mit.edu/timeline/" target="_blank"&gt;intriguing little API&lt;/a&gt; that provides a nice interface for displaying events on a timeline.&amp;nbsp; It was pretty easy to get my head around it and it's pretty easy to setup and use.&amp;nbsp; It's got a Google Maps-like scrolling interface that is very intuitive.&amp;nbsp; If you're not sure what a timeline looks like, you might want to &lt;a href="http://simile.mit.edu/timeline/examples/jfk/jfk.html" target="_blank"&gt;jump straight to an example&lt;/a&gt; before continuing.&lt;/p&gt; &lt;p&gt;I've don't really like the standard options for browsing a blogs history which typically looks like this:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;January (10)  &lt;li&gt;February (5)  &lt;li&gt;March (11)  &lt;li&gt;...&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Kind of boring, right? So, as a proof of concept, I created a little test project to see what an RSS feed would look like in a timeline.&amp;nbsp; Here's what it looks like for a busy RSS feed like Techmeme (or, &lt;a href="http://rowdydata.com/Rss2Timeline" target="_blank"&gt;view live demo&lt;/a&gt;):&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://rowdydata.com/Rss2Timeline/ScreenCap.jpg"&gt; &lt;/p&gt; &lt;p&gt;RSS feeds don't typically output an entire history so this example isn't all that practical.&amp;nbsp; However, if I had access to the database I could pull in all the posts to create a full blog timeline. As far as practical applications go, I can think of a number of other scenarios for using an interactive timeline over a plain old list:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Displaying event logs&lt;/li&gt; &lt;li&gt;Order tracking&lt;/li&gt; &lt;li&gt;Live event blogging&lt;/li&gt; &lt;li&gt;New user registration&lt;/li&gt; &lt;li&gt;News tickers&lt;/li&gt; &lt;li&gt;Twitter?&lt;/li&gt;&lt;/ul&gt;Take a look at the &lt;a href="http://simile.mit.edu/timeline/" target="_blank"&gt;Simile Timeline page&lt;/a&gt; if you would like more information, documentation, or some better examples.&amp;nbsp; You can also download my little &lt;a href="http://rowdydata.com/Rss2Timeline/Rss2Timeline.zip" target="_blank"&gt;test project/demo&lt;/a&gt;.&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=5988874" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JoshuaStengel/~4/bP6TwjQPklg" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jstengel/archive/tags/AJAX/default.aspx">AJAX</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/UI/default.aspx">UI</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/Multimedia/default.aspx">Multimedia</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/Developer+Tools/default.aspx">Developer Tools</category><feedburner:origLink>http://weblogs.asp.net/jstengel/archive/2008/03/17/cool-timeline-api.aspx</feedburner:origLink></item><item><title>What does it take to qualify for upgrade pricing for VS2008?</title><link>http://feedproxy.google.com/~r/JoshuaStengel/~3/W9-k-9YdhRQ/what-does-it-take-to-qualify-for-upgrade-pricing-for-vs2008.aspx</link><pubDate>Tue, 04 Mar 2008 18:52:21 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:5914374</guid><dc:creator>jstengel</dc:creator><slash:comments>5</slash:comments><wfw:commentRss>http://weblogs.asp.net/jstengel/rsscomments.aspx?PostID=5914374</wfw:commentRss><comments>http://weblogs.asp.net/jstengel/archive/2008/03/04/what-does-it-take-to-qualify-for-upgrade-pricing-for-vs2008.aspx#comments</comments><description>&lt;p&gt;Apparently not much.&amp;nbsp; According to the &lt;a href="http://msdn2.microsoft.com/en-us/vs2008/products/cc263904.aspx" target="_blank"&gt;product pricing page&lt;/a&gt;, all you need is "Any other developer tool".&amp;nbsp; Here is the full eligibility statement found at the &lt;a href="Bottom of page: http://msdn2.microsoft.com/en-us/vs2008/products/cc263904.aspx" target="_blank"&gt;bottom of this page&lt;/a&gt;:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;strong&gt;Upgrade Pricing Eligibility&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;To qualify for upgrade pricing, you must be a licensed user of one of the following products:  &lt;ul&gt; &lt;li&gt;An earlier version of Microsoft Visual Studio  &lt;li&gt;Any other developer tool&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt; &lt;p&gt;The free Visual Web Developer 2008 Express edition binds you to a license and is a developer tool. Hmmm...seems to qualify. Can anyone confirm/debunk this assumption?&lt;/p&gt; &lt;p&gt;How about Dreamweaver or my dusty copy of FrontPage 97?&amp;nbsp; Any &lt;a href="http://wp.netscape.com/communicator/composer/v4.0/index.html" target="_blank"&gt;Netscape Composer 4.0&lt;/a&gt; users still out there?&amp;nbsp; &lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=5914374" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JoshuaStengel/~4/W9-k-9YdhRQ" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jstengel/archive/tags/General+Software+Development/default.aspx">General Software Development</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/Developer+Tools/default.aspx">Developer Tools</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/.NET/default.aspx">.NET</category><feedburner:origLink>http://weblogs.asp.net/jstengel/archive/2008/03/04/what-does-it-take-to-qualify-for-upgrade-pricing-for-vs2008.aspx</feedburner:origLink></item><item><title>Uploading Files: Multiple Files, Progress Bar, No Postback</title><link>http://feedproxy.google.com/~r/JoshuaStengel/~3/8C2JV-O_plI/uploading-files-multiple-files-progress-bar-no-postback.aspx</link><pubDate>Fri, 22 Feb 2008 17:53:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:5840645</guid><dc:creator>jstengel</dc:creator><slash:comments>15</slash:comments><wfw:commentRss>http://weblogs.asp.net/jstengel/rsscomments.aspx?PostID=5840645</wfw:commentRss><comments>http://weblogs.asp.net/jstengel/archive/2008/02/22/uploading-files-multiple-files-progress-bar-no-postback.aspx#comments</comments><description>&lt;P style="BORDER-RIGHT: #ccc 1px dotted; PADDING-RIGHT: 10px; BORDER-TOP: #ccc 1px dotted; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; MARGIN: 20px; BORDER-LEFT: #ccc 1px dotted; COLOR: green; PADDING-TOP: 10px; BORDER-BOTTOM: #ccc 1px dotted"&gt;UPDATE:&amp;nbsp;This is now available as a &lt;A class="" href="http://weblogs.asp.net/jstengel/archive/2008/04/25/flash-file-upload-server-control.aspx" mce_href="http://weblogs.asp.net/jstengel/archive/2008/04/25/flash-file-upload-server-control.aspx"&gt;free ASP.NET control.&lt;/A&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Recently, Joe Stagner &lt;A href="http://www.joeon.net/post/2008/02/New-4-part-series-of-videos-on-DOWNLOADING-with-ASPNET.aspx" target=_blank mce_href="http://www.joeon.net/post/2008/02/New-4-part-series-of-videos-on-DOWNLOADING-with-ASPNET.aspx"&gt;created some videos and talked about 4 upload scenarios&lt;/A&gt; that provide an AJAX-like file upload experience.&amp;nbsp; I've used or looked at all of those options at least once or twice in the past, but they were never quite what I wanted.&amp;nbsp; I wanted something sleek and sexy.&amp;nbsp; Something that really popped. The file upload tool that is my new best friend is &lt;A href="http://swfupload.org/" target=_blank mce_href="http://swfupload.org/"&gt;SWFUpload&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;SWFUpload is a JavaScript/Flash library that degrades to a plain old upload control if there are compatibility problem. It's truly a thing of beauty.&amp;nbsp; The SWFUpload &lt;A href="http://swfupload.org/documentation/demonstration" target=_blank mce_href="http://swfupload.org/documentation/demonstration"&gt;online demos&lt;/A&gt; really don't do it justice as far as demonstrating how pretty you can make it look with a little CSS.&amp;nbsp; Not that I'm the world's greatest designer, but here's an action screen shot of how I integrated it into an ASP.NET application. The picture is a screen capture of SWFUpload in the process of uploading 4 files. The control is inside of an AJAX.NET ModalPopup inside of an UpdatePanel. You can also &lt;A href="http://rowdydata.com/lightbulbs/CMSvideo" target=_blank mce_href="http://rowdydata.com/lightbulbs/CMSvideo"&gt;see it in action&lt;/A&gt; as part of a short demo I did for this project.&amp;nbsp; It's not the greatest video, but you can see the uploading files and photos example about halfway though the video.&lt;/P&gt;
&lt;P align=center&gt;&lt;A href="http://rowdydata.com/lightbulbs/cmsvideo" target=_blank mce_href="http://rowdydata.com/lightbulbs/cmsvideo"&gt;&lt;IMG height=450 src="http://rowdydata.com/lightbulbs/cmsvideo/cmsupload.jpg" width=617 mce_src="http://rowdydata.com/lightbulbs/cmsvideo/cmsupload.jpg"&gt;&lt;/A&gt;&lt;/P&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=5840645" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JoshuaStengel/~4/8C2JV-O_plI" height="1" width="1"/&gt;</description><category domain="http://weblogs.asp.net/jstengel/archive/tags/AJAX/default.aspx">AJAX</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/UI/default.aspx">UI</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/AJAX.NET/default.aspx">AJAX.NET</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/AJAX.NET+Toolkit/default.aspx">AJAX.NET Toolkit</category><category domain="http://weblogs.asp.net/jstengel/archive/tags/Developer+Tools/default.aspx">Developer Tools</category><feedburner:origLink>http://weblogs.asp.net/jstengel/archive/2008/02/22/uploading-files-multiple-files-progress-bar-no-postback.aspx</feedburner:origLink></item></channel></rss>
