<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/rss2full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><rss xmlns:blogChannel="http://backend.userland.com/blogChannelModule" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
  <channel>
    <title>LavaBlast Software Blog</title>
    <description>Help your franchise business get to the next level.</description>
    <link>http://blog.lavablast.com/</link>
    <docs>http://www.rssboard.org/rss-specification</docs>
    <generator>BlogEngine.Net Syndication Generator 1.0.0.0 (http://dotnetblogengine.net/)</generator>
    <language>en-CA</language>
    <blogChannel:blogRoll>http://blog.lavablast.com/opml.axd</blogChannel:blogRoll>
    <blogChannel:blink>http://feeds.feedburner.com/LavablastSoftwareBlog</blogChannel:blink>
    <dc:creator>LavaBlast</dc:creator>
    <dc:title>LavaBlast Software Blog</dc:title>
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/LavablastSoftwareBlog" type="application/rss+xml" /><feedburner:emailServiceId>1595787</feedburner:emailServiceId><feedburner:feedburnerHostname>http://www.feedburner.com</feedburner:feedburnerHostname><item>
      <title>SQL Server - Restore a database backup via the command line</title>
      <description>&lt;p&gt;
&lt;a href="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/SQLServerRes.baktoadatabaseincommandline_E21E/image_2.png"&gt;&lt;img style="border-width: 0px; margin: 0px 0px 10px 10px; display: inline" src="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/SQLServerRes.baktoadatabaseincommandline_E21E/image_thumb.png" border="0" alt="image" title="image" width="408" height="273" align="right" /&gt;&lt;/a&gt; Anyone who&amp;#39;s ever developed a web application in .NET has had to play with a database management system, most probably SQL Server or its free cousin, SQL Server Express.&amp;nbsp; One of the tasks I personally hate doing with our SQL Server Express 2005 databases is restoring them from a backup, using SQL Management Studio.&amp;nbsp; We sometimes restore the &lt;a href="http://www.lavablast.com/en/lb_pointofsale.aspx"&gt;point of sale&lt;/a&gt; database used by our customers to track down various issues or to build reports using their data as our test set. The process is not that long when you restore a backup from your own machine (restoring the MDF and LDF files to their original directory). If you restore databases from foreign systems, the process is simple only if both systems stored their databases in the same directory, which is rarely the case.
&lt;/p&gt;
&lt;p&gt;
For example, I use Windows Vista x64 and our dedicated server uses a 32-bit version of Windows 2003.&amp;nbsp; Our data is stored in the default SQL Server directory, which is in the Program Files folder.&amp;nbsp; However, when using a 64-bit operating system, the program files directory is different (C:\Program Files (x86)).&amp;nbsp; Since the location of the MDF and LDF files are encoded directly in the bak file generated by SQL Server, restoring them via the command line is especially challenging when you don&amp;#39;t control the original locations of the MDF and LDF files, nor their Logical Names.
&lt;/p&gt;
&lt;p&gt;
Our goal is to be able to restore a database by executing a simple command such as this: 
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;
restore.bat LavaBlast
&lt;/pre&gt;
&lt;p&gt;
This command would look for LavaBlast.bak in the current directory and would restore the LavaBlast database to a default location on your computer where you want to store your MDF and LDF files. 
&lt;/p&gt;
&lt;p&gt;
Here is the code for restore.bat:
&lt;/p&gt;
&lt;pre class="csharpcode"&gt;
sqlcmd -S .\SQLEXPRESS -i attachDB.sql -v database=&amp;quot;%1&amp;quot; -v root=&amp;quot;%CD%&amp;quot;
&lt;/pre&gt;
&lt;p&gt;
We are simply calling sqlcmd (added to our path) to connect to our local instance of SQL Server Express and we are executing an SQL file (attachDB.sql) which includes two variables: database and root (the current path). 
&lt;/p&gt;
&lt;p&gt;
Here is the code for attachDB.sql:
&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;USE&lt;/span&gt; MASTER
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;GO&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;IF&lt;/span&gt; &lt;span class="kwrd"&gt;EXISTS&lt;/span&gt; (&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; * &lt;span class="kwrd"&gt;FROM&lt;/span&gt; sys.objects &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; object_id = OBJECT_ID(N&lt;span class="str"&gt;&amp;#39;[dbo].[$(database)]&amp;#39;&lt;/span&gt;) &lt;span class="kwrd"&gt;AND&lt;/span&gt; type &lt;span class="kwrd"&gt;in&lt;/span&gt; (N&lt;span class="str"&gt;&amp;#39;U&amp;#39;&lt;/span&gt;))
&lt;/pre&gt;
&lt;pre&gt;
  &lt;span class="kwrd"&gt;ALTER&lt;/span&gt; &lt;span class="kwrd"&gt;DATABASE&lt;/span&gt; $(&lt;span class="kwrd"&gt;database&lt;/span&gt;) &lt;span class="kwrd"&gt;SET&lt;/span&gt; SINGLE_USER &lt;span class="kwrd"&gt;WITH&lt;/span&gt; &lt;span class="kwrd"&gt;ROLLBACK&lt;/span&gt; &lt;span class="kwrd"&gt;IMMEDIATE&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;create&lt;/span&gt; &lt;span class="kwrd"&gt;table&lt;/span&gt; #backupInformation (LogicalName &lt;span class="kwrd"&gt;varchar&lt;/span&gt;(100),
&lt;/pre&gt;
&lt;pre class="alt"&gt;
PhysicalName &lt;span class="kwrd"&gt;varchar&lt;/span&gt;(100),
&lt;/pre&gt;
&lt;pre&gt;
Type &lt;span class="kwrd"&gt;varchar&lt;/span&gt;(1),
&lt;/pre&gt;
&lt;pre class="alt"&gt;
FileGroupName &lt;span class="kwrd"&gt;varchar&lt;/span&gt;(50) ,
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;Size&lt;/span&gt; bigint ,
&lt;/pre&gt;
&lt;pre class="alt"&gt;
MaxSize bigint,
&lt;/pre&gt;
&lt;pre&gt;
FileId &lt;span class="kwrd"&gt;int&lt;/span&gt;,
&lt;/pre&gt;
&lt;pre class="alt"&gt;
CreateLSN &lt;span class="kwrd"&gt;int&lt;/span&gt;,
&lt;/pre&gt;
&lt;pre&gt;
DropLSN &lt;span class="kwrd"&gt;int&lt;/span&gt;,
&lt;/pre&gt;
&lt;pre class="alt"&gt;
UniqueId uniqueidentifier,
&lt;/pre&gt;
&lt;pre&gt;
ReadOnlyLSN &lt;span class="kwrd"&gt;int&lt;/span&gt;,
&lt;/pre&gt;
&lt;pre class="alt"&gt;
ReadWriteLSN &lt;span class="kwrd"&gt;int&lt;/span&gt;,
&lt;/pre&gt;
&lt;pre&gt;
BackupSizeInBytes &lt;span class="kwrd"&gt;int&lt;/span&gt;,
&lt;/pre&gt;
&lt;pre class="alt"&gt;
SourceBlockSize &lt;span class="kwrd"&gt;int&lt;/span&gt;,
&lt;/pre&gt;
&lt;pre&gt;
FileGroupId &lt;span class="kwrd"&gt;int&lt;/span&gt;,
&lt;/pre&gt;
&lt;pre class="alt"&gt;
LogGroupGUID uniqueidentifier,
&lt;/pre&gt;
&lt;pre&gt;
DifferentialBaseLSN bigint,
&lt;/pre&gt;
&lt;pre class="alt"&gt;
DifferentialBaseGUID uniqueidentifier,
&lt;/pre&gt;
&lt;pre&gt;
IsReadOnly &lt;span class="kwrd"&gt;bit&lt;/span&gt;, IsPresent &lt;span class="kwrd"&gt;bit&lt;/span&gt; )
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
insert &lt;span class="kwrd"&gt;into&lt;/span&gt; #backupInformation &lt;span class="kwrd"&gt;exec&lt;/span&gt;(&lt;span class="str"&gt;&amp;#39;restore filelistonly from disk = &amp;#39;&lt;/span&gt;&lt;span class="str"&gt;&amp;#39;$(root)\$(database).bak&amp;#39;&lt;/span&gt;&lt;span class="str"&gt;&amp;#39;&amp;#39;&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @logicalNameD &lt;span class="kwrd"&gt;varchar&lt;/span&gt;(255);
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @logicalNameL &lt;span class="kwrd"&gt;varchar&lt;/span&gt;(255);
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;select top 1&lt;/span&gt; @logicalNameD = LogicalName &lt;span class="kwrd"&gt;from&lt;/span&gt; #backupInformation &lt;span class="kwrd"&gt;where&lt;/span&gt; Type = &lt;span class="str"&gt;&amp;#39;D&amp;#39;&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;select top 1&lt;/span&gt; @logicalNameL = LogicalName &lt;span class="kwrd"&gt;from&lt;/span&gt; #backupInformation &lt;span class="kwrd"&gt;where&lt;/span&gt; Type = &lt;span class="str"&gt;&amp;#39;L&amp;#39;&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;DROP&lt;/span&gt; &lt;span class="kwrd"&gt;TABLE&lt;/span&gt; #backupInformation 
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;RESTORE&lt;/span&gt; &lt;span class="kwrd"&gt;DATABASE&lt;/span&gt; $(&lt;span class="kwrd"&gt;database&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;FROM&lt;/span&gt; &lt;span class="kwrd"&gt;DISK&lt;/span&gt; = &lt;span class="str"&gt;&amp;#39;$(root)\$(database).bak&amp;#39;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;WITH&lt;/span&gt; REPLACE,
&lt;/pre&gt;
&lt;pre class="alt"&gt;
MOVE @logicalNameD &lt;span class="kwrd"&gt;TO&lt;/span&gt; &lt;span class="str"&gt;&amp;#39;C:\Program Files (x86)\Microsoft SQL Server\MSSQL.1\MSSQL\Data\$(database).mdf&amp;#39;&lt;/span&gt;,
&lt;/pre&gt;
&lt;pre&gt;
MOVE @logicalNameL &lt;span class="kwrd"&gt;TO&lt;/span&gt; &lt;span class="str"&gt;&amp;#39;C:\Program Files (x86)\Microsoft SQL Server\MSSQL.1\MSSQL\Data\$(database).ldf&amp;#39;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;GO&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Simply put, we are extracting the logical names (and other metadata) from the .bak file into a temporary table. We then use those values to restore the MDF and LDF to the correct location, instead of the ones specified in the .bak file. 
&lt;/p&gt;
&lt;p&gt;
If you want to use this script, simply ensure you change the location of your SQL Server data files (the last lines in the SQL file) and you should be good to go. Please note that in its current form, the script only supports files with one MDF and one LDF file in the database backup. Furthermore, it assumes your .bak file has the same name as the database you want to import. We could also enhance the script by automatically adding permissions to the ASP.NET user after restoring the database. Feel free to post any enhancements you make in this post&amp;#39;s comments and I hope you&amp;#39;ll find this script useful! Enjoy.
&lt;/p&gt;
&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblog.lavablast.com%2fpost%2f2008%2f10%2fSQL-Server-Restore-a-bak-to-a-database-in-command-line.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblog.lavablast.com%2fpost%2f2008%2f10%2fSQL-Server-Restore-a-bak-to-a-database-in-command-line.aspx&amp;amp;border=660000&amp;amp;fgcolor=660000&amp;amp;bgcolor=FF9900&amp;amp;cbgcolor=FFFF00" border="0" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;
</description>
      <link>http://feeds.feedburner.com/~r/LavablastSoftwareBlog/~3/420728512/post.aspx</link>
      <author>EtienneT</author>
      <comments>http://blog.lavablast.com/post/2008/10/SQL-Server-Restore-a-bak-to-a-database-in-command-line.aspx#comment</comments>
      <guid isPermaLink="false">http://blog.lavablast.com/post.aspx?id=27614bf8-4ee3-4c8a-9a54-c983fb204289</guid>
      <pubDate>Tue, 14 Oct 2008 12:45:00 -0400</pubDate>
      <category>Software</category>
      <dc:publisher>EtienneT</dc:publisher>
      <pingback:server>http://blog.lavablast.com/pingback.axd</pingback:server>
      <pingback:target>http://blog.lavablast.com/post.aspx?id=27614bf8-4ee3-4c8a-9a54-c983fb204289</pingback:target>
      <slash:comments>1</slash:comments>
      <trackback:ping>http://blog.lavablast.com/trackback.axd?id=27614bf8-4ee3-4c8a-9a54-c983fb204289</trackback:ping>
      <wfw:comment>http://blog.lavablast.com/post/2008/10/SQL-Server-Restore-a-bak-to-a-database-in-command-line.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.lavablast.com/syndication.axd?post=27614bf8-4ee3-4c8a-9a54-c983fb204289</wfw:commentRss>
    <feedburner:origLink>http://blog.lavablast.com/post.aspx?id=27614bf8-4ee3-4c8a-9a54-c983fb204289</feedburner:origLink></item>
    <item>
      <title>Jason Kealey and Etienne Tremblay featured in National Capital Scan</title>
      <description>&lt;p&gt; &lt;a href="http://www.nationalcapitalscan.ca/news/print_editions/files/090808SCAN.pdf"&gt;&lt;img style="margin: 10px; border: 0px" src="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/JasonKealeyandEtienneTremblayfeaturedinN_13EA1/jket_3.png" border="0" alt="jket" width="263" height="387" align="right" /&gt;&lt;/a&gt;Two of LavaBlast&amp;#39;s founders (Etienne and myself) are featured in &lt;a href="http://www.nationalcapitalscan.ca/news/print_editions/files/090808SCAN.pdf"&gt;this month&amp;#39;s&lt;/a&gt; &lt;a href="http://www.nationalcapitalscan.ca"&gt;National Capital Scan&lt;/a&gt;, an independent news leader for Ottawa&amp;#39;s Tech Community. As we are proud to be &lt;a href="http://www.site.uottawa.ca/"&gt;University of Ottawa alumni&lt;/a&gt;, it is always a pleasure to keep in touch with the university and new software engineering students. In addition to this article about our launching our software company, I will be sharing lessons learned at the &lt;em&gt;Students As Innovators&lt;/em&gt; workshop later this month at the &lt;a href="http://www.site.uottawa.ca/"&gt;School of Information Technology and Engineering&lt;/a&gt;.  &lt;/p&gt; &lt;p&gt; Additionally, we&amp;#39;re actively helping other startups in the Ottawa and Montreal regions, many of which we met at &lt;a href="http://www.thecodefactory.ca"&gt;The Code Factory&lt;/a&gt;, the &lt;a href="http://www.thecodefactory.ca"&gt;Ottawa-based co-working location&lt;/a&gt;.&amp;nbsp; Ian Graham is busy organizing tons of events which we strongly recommend you attend if you&amp;#39;re interested in getting known in the Ottawa software community.  &lt;/p&gt; &lt;br style="clear:both"/&gt;</description>
      <link>http://feeds.feedburner.com/~r/LavablastSoftwareBlog/~3/390707337/post.aspx</link>
      <author>jkealey</author>
      <comments>http://blog.lavablast.com/post/2008/09/Jason-Kealey-and-Etienne-Tremblay-featured-in-National-Capital-Scan.aspx#comment</comments>
      <guid isPermaLink="false">http://blog.lavablast.com/post.aspx?id=1a762a8a-654f-47a0-b7eb-a2c2db47a91c</guid>
      <pubDate>Thu, 11 Sep 2008 22:39:00 -0400</pubDate>
      <category>News</category>
      <dc:publisher>jkealey</dc:publisher>
      <pingback:server>http://blog.lavablast.com/pingback.axd</pingback:server>
      <pingback:target>http://blog.lavablast.com/post.aspx?id=1a762a8a-654f-47a0-b7eb-a2c2db47a91c</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://blog.lavablast.com/trackback.axd?id=1a762a8a-654f-47a0-b7eb-a2c2db47a91c</trackback:ping>
      <wfw:comment>http://blog.lavablast.com/post/2008/09/Jason-Kealey-and-Etienne-Tremblay-featured-in-National-Capital-Scan.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.lavablast.com/syndication.axd?post=1a762a8a-654f-47a0-b7eb-a2c2db47a91c</wfw:commentRss>
    <feedburner:origLink>http://blog.lavablast.com/post.aspx?id=1a762a8a-654f-47a0-b7eb-a2c2db47a91c</feedburner:origLink></item>
    <item>
      <title>LavaBlast Selected as a Red Herring Canada Top 50 Finalist</title>
      <description>&lt;p&gt;We've been busy these lasts few weeks on a number of projects, but I thought I'd like you know that we were selected as an innovative Canadian software start-up. &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Red Herring Magazine has named &lt;a href="http://www.lavablast.com"&gt;LavaBlast Software&lt;/a&gt; a finalist for the &amp;quot;Red Herring Top 50 Canada&amp;quot; award, a prestigious list honoring this year&amp;#8217;s most promising private technology ventures in Canada. The Red Herring editorial team used an intensely competitive process to select the most innovative companies from a pool of over 300, leaving 100 finalists vying for this prestigious award. The names of all 100 companies short&amp;#8211;listed as finalists for the &amp;quot;Red Herring Top 50 Canada 2008&amp;quot; can be found online at: &lt;a href="http://www.herringevents.com/canada08/Canada50.html"&gt;http://www.herringevents.com/canada08/Canada50.html&lt;/a&gt; &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;a href="http://www.herringevents.com/canada08/Canada50.html"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; margin: 20px; border-right-width: 0px" height="136" alt="RHCanada finalist logo" src="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastisafinalistfortheRedHerringTop5_C582/RHCanada%20finalist%20logo_3.jpg" width="136" align="right" border="0" /&gt;&lt;/a&gt;Read more in our &lt;a href="http://www.lavablast.com/pr/20080826_RedHerring2008_PressRelease.pdf"&gt;press release&lt;/a&gt;.&amp;#160; &lt;/p&gt;  &lt;p&gt;While I was enjoying the weather, Toronto Tech Jobs took the time to peruse everyone's website to figure out who's hiring software engineers! &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://torontotechjobs.wordpress.com/2008/08/28/red-herring-canada-2008-a-f/"&gt;Red Herring Canada 2008 (A-F)&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://torontotechjobs.wordpress.com/2008/08/29/red-herring-canada-2008-g-n/"&gt;Red Herring Canada 2008 (G-N)&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://torontotechjobs.wordpress.com/2008/09/02/red-herring-canada-2008-o-s/"&gt;Red Herring Canada 2008 (O-S)&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://torontotechjobs.wordpress.com/2008/09/03/red-herring-canada-2008-t-z/"&gt;Red Herring Canada 2008 (T-Z)&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Congratulations to the other finalists.&lt;/p&gt;</description>
      <link>http://feeds.feedburner.com/~r/LavablastSoftwareBlog/~3/378300541/post.aspx</link>
      <author>jkealey</author>
      <comments>http://blog.lavablast.com/post/2008/08/LavaBlast-Selected-as-a-Red-Herring-Canada-Top-50-Finalist.aspx#comment</comments>
      <guid isPermaLink="false">http://blog.lavablast.com/post.aspx?id=60a53f4f-f9f9-4c08-9369-c370aed3cd18</guid>
      <pubDate>Fri, 29 Aug 2008 14:02:52 -0400</pubDate>
      <category>News</category>
      <dc:publisher>jkealey</dc:publisher>
      <pingback:server>http://blog.lavablast.com/pingback.axd</pingback:server>
      <pingback:target>http://blog.lavablast.com/post.aspx?id=60a53f4f-f9f9-4c08-9369-c370aed3cd18</pingback:target>
      <slash:comments>2</slash:comments>
      <trackback:ping>http://blog.lavablast.com/trackback.axd?id=60a53f4f-f9f9-4c08-9369-c370aed3cd18</trackback:ping>
      <wfw:comment>http://blog.lavablast.com/post/2008/08/LavaBlast-Selected-as-a-Red-Herring-Canada-Top-50-Finalist.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.lavablast.com/syndication.axd?post=60a53f4f-f9f9-4c08-9369-c370aed3cd18</wfw:commentRss>
    <feedburner:origLink>http://blog.lavablast.com/post.aspx?id=60a53f4f-f9f9-4c08-9369-c370aed3cd18</feedburner:origLink></item>
    <item>
      <title>BlogEngine.net Post Security</title>
      <description>&lt;p&gt;
&lt;a href="http://www.dotnetblogengine.net/"&gt;BlogEngine.net&lt;/a&gt; 1.3/1.4 supports user roles.&amp;nbsp; But we can&amp;#39;t seem to be able to make it mandatory for users to sign in to see blog posts.&amp;nbsp; That&amp;#39;s not something you usually want on a public blog, but for a corporate blog, maybe you want to make sure your news only gets to the people you want.&amp;nbsp; This seemed like a perfect candidate for a &lt;a href="http://www.dotnetblogengine.net/page/extensions.aspx"&gt;BlogEngine extension&lt;/a&gt;.
&lt;/p&gt;
&lt;h2&gt;User Filtering&lt;/h2&gt;  
&lt;p&gt;
In our scenario, we don&amp;rsquo;t want any unregistered users to be able to see blog posts.&amp;nbsp; This can be easily checked by calling Membership.GetUser() and ensuring the returned value is not null.&amp;nbsp; We could filter out specific users as well, but we didn&amp;rsquo;t implement this feature in our extension.
&lt;/p&gt;
&lt;h2&gt;Post Filtering&lt;/h2&gt;  
&lt;p&gt;
It could be interesting to restrict who can see the posts in a specific blog category.&amp;nbsp; For example, a blog category &amp;ldquo;Top Secret&amp;rdquo; which can only be read by your company&amp;#39;s upper management&amp;hellip;&amp;nbsp; Not very likely in a blog, but you get the point.&amp;nbsp; Our extension does this filtering by associating a blog Category with a membership Role in the extension&amp;rsquo;s settings.
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/BlogEngine.netPostSecurity_892D/image_3.png" border="0" alt="image" title="image" width="631" height="231" /&gt; 
&lt;/p&gt;
&lt;p&gt;
By associating a membership role with a blog category name, the extension ensures the user has this role before displaying a post associated with this blog category name.&amp;nbsp; If you add two roles for the same category, posts with this category will only be served if the user has both roles.
&lt;/p&gt;
&lt;p&gt;
Adding a setting with an empty category name will ensure that all posts require a particular role. 
&lt;/p&gt;
&lt;h2&gt;Code&lt;/h2&gt;  
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Data;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Configuration;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.Security;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.UI;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.UI.HtmlControls;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.UI.WebControls;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.UI.WebControls.WebParts;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; BlogEngine.Core;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; BlogEngine.Core.Web.Controls;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&lt;span class="rem"&gt;/// Summary description for PostSecurity&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
[Extension(&lt;span class="str"&gt;&amp;quot;Checks to see if a user can see this blog post.&amp;quot;&lt;/span&gt;,
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="str"&gt;&amp;quot;1.0&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;&amp;lt;a href=\&amp;quot;http://www.lavablast.com\&amp;quot;&amp;gt;LavaBlast.com&amp;lt;/a&amp;gt;&amp;quot;&lt;/span&gt;)]
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; PostSecurity
&lt;/pre&gt;
&lt;pre&gt;
{
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;protected&lt;/span&gt; ExtensionSettings settings = &lt;span class="kwrd"&gt;null&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; PostSecurity()
&lt;/pre&gt;
&lt;pre&gt;
    {
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        Post.Serving += &lt;span class="kwrd"&gt;new&lt;/span&gt; EventHandler&amp;lt;ServingEventArgs&amp;gt;(Post_Serving);
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        ExtensionSettings s = &lt;span class="kwrd"&gt;new&lt;/span&gt; ExtensionSettings(&lt;span class="str"&gt;&amp;quot;PostSecurity&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        s.AddParameter(&lt;span class="str"&gt;&amp;quot;Role&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;Role&amp;quot;&lt;/span&gt;, 50, &lt;span class="kwrd"&gt;true&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre&gt;
        s.AddParameter(&lt;span class="str"&gt;&amp;quot;Category&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;Category&amp;quot;&lt;/span&gt;, 50);
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="rem"&gt;// describe specific rules for entering parameters&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        s.Help = &lt;span class="str"&gt;&amp;quot;Checks to see if the user has any of those roles before displaying the post. &amp;quot;&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre&gt;
        s.Help += &lt;span class="str"&gt;&amp;quot;You can associate a role with a specific category. &amp;quot;&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        s.Help += &lt;span class="str"&gt;&amp;quot;All posts having this category will require that the user have the role. &amp;quot;&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre&gt;
        s.Help += &lt;span class="str"&gt;&amp;quot;A parameter with only a role without a category will enable to filter all posts to this role. &amp;quot;&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
        s.AddValues(&lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;[] { &lt;span class="str"&gt;&amp;quot;Registered&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt; });
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
        ExtensionManager.ImportSettings(s);
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        settings = ExtensionManager.GetSettings(&lt;span class="str"&gt;&amp;quot;PostSecurity&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre&gt;
    }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Post_Serving(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, ServingEventArgs e)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    {
&lt;/pre&gt;
&lt;pre&gt;
        Post post = (Post)sender;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="kwrd"&gt;bool&lt;/span&gt; continu = &lt;span class="kwrd"&gt;false&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        MembershipUser user = Membership.GetUser();
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        continu = user != &lt;span class="kwrd"&gt;null&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (user != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre&gt;
        {
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; categories = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;();
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Category cat &lt;span class="kwrd"&gt;in&lt;/span&gt; post.Categories)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                categories.Add(cat.Title);
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            &lt;span class="kwrd"&gt;string&lt;/span&gt;[] r = Roles.GetRolesForUser();
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; roles = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(r);
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            DataTable table = settings.GetDataTable();
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (DataRow row &lt;span class="kwrd"&gt;in&lt;/span&gt; table.Rows)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            {
&lt;/pre&gt;
&lt;pre&gt;
                &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty((&lt;span class="kwrd"&gt;string&lt;/span&gt;)row[&lt;span class="str"&gt;&amp;quot;Category&amp;quot;&lt;/span&gt;]))
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                    continu &amp;amp;= roles.Contains((&lt;span class="kwrd"&gt;string&lt;/span&gt;)row[&lt;span class="str"&gt;&amp;quot;Role&amp;quot;&lt;/span&gt;]);
&lt;/pre&gt;
&lt;pre&gt;
                &lt;span class="kwrd"&gt;else&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                {
&lt;/pre&gt;
&lt;pre&gt;
                    &lt;span class="kwrd"&gt;if&lt;/span&gt; (categories.Contains((&lt;span class="kwrd"&gt;string&lt;/span&gt;)row[&lt;span class="str"&gt;&amp;quot;Category&amp;quot;&lt;/span&gt;]))
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                        continu &amp;amp;= roles.Contains((&lt;span class="kwrd"&gt;string&lt;/span&gt;)row[&lt;span class="str"&gt;&amp;quot;Role&amp;quot;&lt;/span&gt;]);
&lt;/pre&gt;
&lt;pre&gt;
                }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            }
&lt;/pre&gt;
&lt;pre&gt;
        }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
        e.Cancel = !continu;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    }
&lt;/pre&gt;
&lt;pre&gt;
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Simply saving this code in a .cs and putting it in your App_Code/Extensions for BlogEngine.net shall enable the plugin.
&lt;/p&gt;
&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblog.lavablast.com%2fpost%2f2008%2f08%2fBlogEnginenet-Post-Security.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblog.lavablast.com%2fpost%2f2008%2f08%2fBlogEnginenet-Post-Security.aspx&amp;amp;border=660000&amp;amp;fgcolor=660000&amp;amp;bgcolor=FF9900&amp;amp;cbgcolor=FFFF00" border="0" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;
</description>
      <link>http://feeds.feedburner.com/~r/LavablastSoftwareBlog/~3/364161959/post.aspx</link>
      <author>EtienneT</author>
      <comments>http://blog.lavablast.com/post/2008/08/BlogEnginenet-Post-Security.aspx#comment</comments>
      <guid isPermaLink="false">http://blog.lavablast.com/post.aspx?id=ceb887a9-f0d1-4379-815a-513cda5d5fc8</guid>
      <pubDate>Wed, 13 Aug 2008 15:23:00 -0400</pubDate>
      <category>Software</category>
      <dc:publisher>EtienneT</dc:publisher>
      <pingback:server>http://blog.lavablast.com/pingback.axd</pingback:server>
      <pingback:target>http://blog.lavablast.com/post.aspx?id=ceb887a9-f0d1-4379-815a-513cda5d5fc8</pingback:target>
      <slash:comments>10</slash:comments>
      <trackback:ping>http://blog.lavablast.com/trackback.axd?id=ceb887a9-f0d1-4379-815a-513cda5d5fc8</trackback:ping>
      <wfw:comment>http://blog.lavablast.com/post/2008/08/BlogEnginenet-Post-Security.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.lavablast.com/syndication.axd?post=ceb887a9-f0d1-4379-815a-513cda5d5fc8</wfw:commentRss>
    <feedburner:origLink>http://blog.lavablast.com/post.aspx?id=ceb887a9-f0d1-4379-815a-513cda5d5fc8</feedburner:origLink></item>
    <item>
      <title>SubSonic v2.1 Controller and Utilities</title>
      <description>&lt;p&gt;
We&amp;#39;ve done a few posts about how we use &lt;a href="http://www.subsonicproject.com/"&gt;SubSonic&lt;/a&gt; here at &lt;a href="http://www.lavablast.com"&gt;LavaBlast&lt;/a&gt;. Recently, &lt;a href="http://blog.wekeroad.com/blog/subsonic-2-1-released/"&gt;SubSonic v2.1&lt;/a&gt; was released and we upgraded the code we&amp;#39;ve previously published to support this new version. We&amp;#39;ve blogged about &lt;a href="http://blog.lavablast.com/post/2008/07/Upgrading-to-SubSonic-v21.aspx"&gt;our changes in the past&lt;/a&gt; and not much has changed since, but we did get a request to post our source code, so here it is. I&amp;#39;ve actually included a bit more code in this release so that this blog post has a bit more substance!
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.lavablast.com/uploads/LavaBlastSubSonic.zip"&gt;Download the source code.&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
The file contains our &lt;a href="http://blog.lavablast.com/post/2007/11/SubSonic-magic.aspx"&gt;SubSonicController&lt;/a&gt;, &lt;a href="http://blog.lavablast.com/post/2007/11/SubSonic-object-change-tracking.aspx"&gt;SubSonicHelper&lt;/a&gt;, and our associated code generation templates. Nothing new to see here, except that you get downloadable code. We unfortunately did not have time to play with the new Query engine all that much, so our controller still uses the old one (which is used throughout our codebase). If anyone would like to augment our code to support the new query engine and post it in the comments, that would be great! Moving to the new query engine would circumvent the OR query limitation related to the search fields we&amp;#39;ve mentioned in the past. 
&lt;/p&gt;
&lt;h2&gt;Auditing using SubSonic&lt;/h2&gt;  
&lt;p&gt;
We like to &lt;a href="http://blog.lavablast.com/post/2007/11/SubSonic-object-change-tracking.aspx"&gt;log certain things in our Electronic Journal&lt;/a&gt; as it gives us ways to debug more efficiently, and provides us with a way to keep track of who changed what in case something breaks. We&amp;#39;ve included an SQL script that generates our ElectronicJournal table, and code which allows us to save events in the table. We&amp;#39;ve wired it up to our &lt;a href="http://blog.lavablast.com/post/2007/11/SubSonic-magic.aspx"&gt;SubSonicController so that we can log all object updates&lt;/a&gt;, for example. What you log is your own business and it depends on your needs and performance requirements. 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/SubSonicv2.1ControllerandUtilities_C407/ej_4.jpg"&gt;&lt;img style="border-width: 0px" src="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/SubSonicv2.1ControllerandUtilities_C407/ej_thumb_1.jpg" border="0" alt="ej" width="198" height="236" /&gt;&lt;/a&gt;     
&lt;/p&gt;
&lt;p&gt;
We&amp;#39;ve built an administrative interface over this table allowing us to navigate efficiently through the events. (Each of our pages in &lt;a href="http://www.lavablast.com/en/lb_franchiseblast.aspx"&gt;FranchiseBlast&lt;/a&gt; extends from generic controls which list/filter/page rows using our ObjectDataSource, effectively re-using the code we&amp;#39;re presenting here.) 
&lt;/p&gt;
&lt;h3&gt;Various notes&lt;/h3&gt;  
&lt;ul&gt;
	&lt;li&gt;Remember not to mix AND and OR in the current version of this code, with the old query engine. &lt;/li&gt;    
	&lt;li&gt;Don&amp;#39;t log everything on high volume sites, for obvious reasons. &lt;/li&gt;    
	&lt;li&gt;&lt;a href="http://code.google.com/p/subsonicproject/issues/detail?id=3"&gt;Issue 3&lt;/a&gt; is still open and waiting to be committed. The others bugs I &lt;a href="http://blog.lavablast.com/post/2008/07/Upgrading-to-SubSonic-v21.aspx"&gt;previously reported&lt;/a&gt; (and &lt;a href="http://code.google.com/p/subsonicproject/issues/detail?id=6"&gt;a new one&lt;/a&gt;) have been committed. &lt;/li&gt;    
	&lt;li&gt;We removed the &lt;a href="http://blog.lavablast.com/post/2008/07/Upgrading-to-SubSonic-v21.aspx"&gt;ToList() which we added last time&lt;/a&gt;, because GetList() is already present. (Thanks to our readers for noticing!) &lt;/li&gt;    
	&lt;li&gt;&lt;strong&gt;We replaced all calls to IsLoaded() to !IsNew() in our codebase.&lt;/strong&gt; &lt;a href="http://forums.subsonicproject.com/forums/p/3361/14481.aspx"&gt;Click here to learn why&lt;/a&gt;. &lt;/li&gt; 
&lt;/ul&gt;
&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblog.lavablast.com%2fpost%2f2008%2f08%2fSubSonic-v21-Controller-and-Utilities.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblog.lavablast.com%2fpost%2f2008%2f08%2fSubSonic-v21-Controller-and-Utilities.aspx&amp;amp;border=660000&amp;amp;fgcolor=660000&amp;amp;bgcolor=FF9900&amp;amp;cbgcolor=FFFF00" border="0" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;
</description>
      <link>http://feeds.feedburner.com/~r/LavablastSoftwareBlog/~3/355446125/post.aspx</link>
      <author>JKealey</author>
      <comments>http://blog.lavablast.com/post/2008/08/SubSonic-v21-Controller-and-Utilities.aspx#comment</comments>
      <guid isPermaLink="false">http://blog.lavablast.com/post.aspx?id=118193ab-e492-459a-925d-991545c4782f</guid>
      <pubDate>Mon, 04 Aug 2008 11:45:00 -0400</pubDate>
      <category>Software</category>
      <dc:publisher>JKealey</dc:publisher>
      <pingback:server>http://blog.lavablast.com/pingback.axd</pingback:server>
      <pingback:target>http://blog.lavablast.com/post.aspx?id=118193ab-e492-459a-925d-991545c4782f</pingback:target>
      <slash:comments>3</slash:comments>
      <trackback:ping>http://blog.lavablast.com/trackback.axd?id=118193ab-e492-459a-925d-991545c4782f</trackback:ping>
      <wfw:comment>http://blog.lavablast.com/post/2008/08/SubSonic-v21-Controller-and-Utilities.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.lavablast.com/syndication.axd?post=118193ab-e492-459a-925d-991545c4782f</wfw:commentRss>
    <feedburner:origLink>http://blog.lavablast.com/post.aspx?id=118193ab-e492-459a-925d-991545c4782f</feedburner:origLink></item>
    <item>
      <title>The Code Factory in the News</title>
      <description>&lt;p&gt;
We&amp;#39;re happy to see that our client &lt;a href="http://www.thecodefactory.ca"&gt;The Code Factory&lt;/a&gt;, &lt;a href="http://www.thecodefactory.ca"&gt;an Ottawa-based software co-working franchise&lt;/a&gt;, was recently featured on the local news. Some of us were on site while the spot was filmed and it was an interesting (yet stressful) experience to be filmed when you&amp;#39;re trying to draft out the features to include in the next release! 
&lt;/p&gt;
&lt;table border="0" cellspacing="0" cellpadding="2" width="100%"&gt;
	&lt;tbody&gt;
		&lt;tr&gt;
			&lt;td width="300" valign="top"&gt;
			&lt;p&gt;
			&lt;a href="http://ottawa.ctv.ca/servlet/an/local/CTVNews/20080719/OTT_technow_code_factory_080719/20080720/?hub=OttawaHome"&gt;&lt;img style="margin: 10px 10px 0px 0px; border-width: 0px" src="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/TheCodeFactoryinthenews_C74A/ctv_3.jpg" border="0" alt="ctv" title="ctv" width="335" height="341" align="left" /&gt;&lt;/a&gt;
			&lt;/p&gt;
			&lt;/td&gt;
			&lt;td valign="top"&gt;
			&lt;h2&gt;Twitter + Co-working&lt;/h2&gt;
			&lt;p&gt;
			This coincides with our recent addition of a cool little feature to The Code Factory&amp;#39;s &lt;a href="http://www.lavablast.com/en/lb_kiosk.aspx"&gt;interactive kiosk&lt;/a&gt;. We&amp;#39;re now publishing events to &lt;a href="http://www.twitter.com"&gt;Twitter&lt;/a&gt; when people check-in and check-out of the location. Of course, members can choose to hide their activities for privacy reasons, but this serves as an interesting off-site complement to the in-store kiosk which indicates who&amp;#39;s currently on location. If you follow &lt;a href="http://twitter.com/TheCodeFactory"&gt;TheCodeFactory on Twitter&lt;/a&gt;, you can see when your friends arrive and decide to head out there yourself!
			&lt;/p&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
</description>
      <link>http://feeds.feedburner.com/~r/LavablastSoftwareBlog/~3/344600091/post.aspx</link>
      <author>JKealey</author>
      <comments>http://blog.lavablast.com/post/2008/07/The-Code-Factory-in-the-news.aspx#comment</comments>
      <guid isPermaLink="false">http://blog.lavablast.com/post.aspx?id=5e55961b-40e5-4a2e-a32e-dc93daab5a5b</guid>
      <pubDate>Thu, 24 Jul 2008 08:41:00 -0400</pubDate>
      <category>News</category>
      <dc:publisher>JKealey</dc:publisher>
      <pingback:server>http://blog.lavablast.com/pingback.axd</pingback:server>
      <pingback:target>http://blog.lavablast.com/post.aspx?id=5e55961b-40e5-4a2e-a32e-dc93daab5a5b</pingback:target>
      <slash:comments>1</slash:comments>
      <trackback:ping>http://blog.lavablast.com/trackback.axd?id=5e55961b-40e5-4a2e-a32e-dc93daab5a5b</trackback:ping>
      <wfw:comment>http://blog.lavablast.com/post/2008/07/The-Code-Factory-in-the-news.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.lavablast.com/syndication.axd?post=5e55961b-40e5-4a2e-a32e-dc93daab5a5b</wfw:commentRss>
    <feedburner:origLink>http://blog.lavablast.com/post.aspx?id=5e55961b-40e5-4a2e-a32e-dc93daab5a5b</feedburner:origLink></item>
    <item>
      <title>jQuery Content Slider Tutorial</title>
      <description>&lt;p&gt;
&lt;a href="http://blog.lavablast.com/SliderMenu/"&gt;Simple Demo (Firefox, IE7, IE6, Opera, Safari)&lt;/a&gt; | &lt;a href="http://www.lavablast.com"&gt;Demo with content&lt;/a&gt; | &lt;a href="http://blog.lavablast.com/uploads/SliderMenu.zip"&gt;Source Code&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
LavaBlast launched a new front page recently and we have incorporated a new jQuery slider. You can see it in action below (in the Flash animation) or you can go see it directly on our &lt;a href="http://www.lavablast.com"&gt;website home page&lt;/a&gt;. 
&lt;/p&gt;
&lt;p&gt;
Scroll down to find out how this little puppy was implemented!
&lt;/p&gt;
&lt;div id="scid:8C92A505-C66E-4dd0-A7AF-2692874158CA:14722e9f-80d8-40b3-b9e3-fd8eef148b85" class="wlWriterSmartContent" style="margin: 0px; padding: 0px; display: inline; float: none"&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" name="FrontPageMenu" width="950" height="552" align="middle"&gt;
	&lt;param name="name" value="FrontPageMenu" /&gt;
	&lt;param name="width" value="950" /&gt;
	&lt;param name="height" value="552" /&gt;
	&lt;param name="bgcolor" value="#F6ECA4" /&gt;
	&lt;param name="align" value="middle" /&gt;
	&lt;param name="pluginspace" value="http://www.macromedia.com/go/getflashplayer" /&gt;
	&lt;param name="quality" value="High" /&gt;
	&lt;param name="src" value="http://blog.lavablast.com/uploads/FrontPageMenu.swf" /&gt;
	&lt;embed type="application/x-shockwave-flash" name="FrontPageMenu" width="950" height="552" bgcolor="#F6ECA4" align="middle" pluginspace="http://www.macromedia.com/go/getflashplayer" quality="High" src="http://blog.lavablast.com/uploads/FrontPageMenu.swf"&gt;&lt;/embed&gt;
&lt;/object&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;/div&gt;
&lt;h2&gt;HTML &amp;amp; CSS&lt;/h2&gt;  
&lt;h3&gt;HTML&lt;/h3&gt;  
&lt;p&gt;
This is the basic ASP.NET in the ASPX page:
&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;FrontMenu&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Bar&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:Repeater&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Repeater&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;onitemdatabound&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Repeater_ItemDataBound&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;ItemTemplate&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;item&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
                    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;a&lt;/span&gt; &lt;span class="attr"&gt;href&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;jFlowControl&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:Label&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;lbl&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
                    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;a&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;spike&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;style&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;z-index:999999&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
                    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;right&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
                    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;ItemTemplate&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:Repeater&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Panel&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;cms:Paragraph&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;paragraph1&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;ContentName&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;frontMenu1&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;cms:Paragraph&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;paragraph2&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;ContentName&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;frontMenu2&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;cms:Paragraph&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;paragraph3&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;ContentName&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;frontMenu3&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;cms:Paragraph&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;paragraph4&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;ContentName&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;frontMenu4&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;cms:Paragraph&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;paragraph6&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;ContentName&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;frontMenu5&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;div&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
This is pretty simple HTML.&amp;nbsp; Everything is enclosed in the main div with the css class FrontMenu.&amp;nbsp; We have the animated bar at the top and the content panel underneath it.&amp;nbsp; The menu bar is generated by a simple repeater control bound to data in our ASP.NET page. Each menu item is a span containing a link that we&amp;rsquo;ll use to change the selected menu item.&amp;nbsp; The Panel div contains multiple dynamic paragraphs from our content management system (&lt;a href="http://www.subsonicproject.com/"&gt;SubSonic CMS&lt;/a&gt;).&amp;nbsp; You could easily change this code to bind to data from another source.
&lt;/p&gt;
&lt;p&gt;
Here is the code behind for this control.&amp;nbsp; We kept it pretty simple:
&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; FrontPageMenu : UserControl
&lt;/pre&gt;
&lt;pre&gt;
{
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Page_Load(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)
&lt;/pre&gt;
&lt;pre&gt;
    {
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (!IsPostBack)
&lt;/pre&gt;
&lt;pre&gt;
        {
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; list = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;();
&lt;/pre&gt;
&lt;pre&gt;
            list.Add(&lt;span class="str"&gt;&amp;quot;How can we help?&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            list.Add(&lt;span class="str"&gt;&amp;quot;Our Products&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre&gt;
            list.Add(&lt;span class="str"&gt;&amp;quot;Hot Features&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            list.Add(&lt;span class="str"&gt;&amp;quot;Testimonials&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre&gt;
            list.Add(&lt;span class="str"&gt;&amp;quot;Read&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
            Repeater.DataSource = list;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            Repeater.DataBind();
&lt;/pre&gt;
&lt;pre&gt;
        }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    }
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Repeater_ItemDataBound(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, RepeaterItemEventArgs e)
&lt;/pre&gt;
&lt;pre&gt;
    {
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
&lt;/pre&gt;
&lt;pre&gt;
        {
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            Label lbl = e.Item.FindControl(&lt;span class="str"&gt;&amp;quot;lbl&amp;quot;&lt;/span&gt;) &lt;span class="kwrd"&gt;as&lt;/span&gt; Label;
&lt;/pre&gt;
&lt;pre&gt;
            lbl.Text = (&lt;span class="kwrd"&gt;string&lt;/span&gt;)e.Item.DataItem;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        }
&lt;/pre&gt;
&lt;pre&gt;
    }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/image_2.png"&gt;&lt;img style="border-width: 0px" src="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/image_thumb.png" border="0" alt="image" title="image" width="893" height="288" /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
The following picture shows how the html menu item elements are rendered.&amp;nbsp; The CSS section of this article will dive deeper in the inner workings of the menu. 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/image_10.png"&gt;&lt;img style="border-width: 0px" src="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/image_thumb_4.png" border="0" alt="image" title="image" width="651" height="125" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;h2&gt;JQuery&lt;/h2&gt;
&lt;h3&gt;jFlow&lt;/h3&gt;
&lt;p&gt;
We used &lt;a href="http://www.gimiti.com/kltan/wordpress/?p=32"&gt;jFlow&lt;/a&gt; to scroll our panels when we click on a menu item.&amp;nbsp; The code was fairly straightforward to use.&amp;nbsp; We included this script in our user control.
&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
$(&lt;span class="str"&gt;&amp;quot;.FrontMenu&amp;quot;&lt;/span&gt;).jFlow({
&lt;/pre&gt;
&lt;pre&gt;
    slides: &lt;span class="str"&gt;&amp;quot;.FrontMenu .Panel&amp;quot;&lt;/span&gt;,
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    width: &lt;span class="str"&gt;&amp;quot;974px&amp;quot;&lt;/span&gt;,
&lt;/pre&gt;
&lt;pre&gt;
    height: &lt;span class="str"&gt;&amp;quot;344px&amp;quot;&lt;/span&gt;,
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    duration: 300
&lt;/pre&gt;
&lt;pre&gt;
});
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
And then we included a simple reference to our script manager.
&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:ScriptManagerProxy&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;proxy&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Scripts&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:ScriptReference&lt;/span&gt; &lt;span class="attr"&gt;Path&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;~/js/jquery.flow.1.0.min.js&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Scripts&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:ScriptManagerProxy&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
We could have used Next and Previous buttons but decided not to.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;h3&gt;IE6 Problems&lt;/h3&gt;
&lt;p&gt;
This menu did require some basic jQuery.&amp;nbsp; Except for the scrolling animation, we could have built almost all of this in pure CSS thanks to the hover pseudo-class. However, Internet Explorer 6 came back from the grave to haunt us&amp;hellip;&amp;nbsp; As we still have some visitors who are using IE6, we could not afford to let our home page break down in IE6.&amp;nbsp; Microsoft gods: please please, hear our prayers and find a way to erase IE6 from the face of earth.&amp;nbsp; But hey, we&amp;#39;ve got work to do and can&amp;#39;t wait five years for the browser to die like IE 5 did.
&lt;/p&gt;
&lt;p&gt;
We discovered that using a:hover in IE6 to change our background image will make the browser crash.&amp;nbsp; We used &lt;a href="http://www.my-debugbar.com/wiki/IETester/HomePage"&gt;IETester&lt;/a&gt; to test the menu in IE6: it made IETester crash.&amp;nbsp; We then tried Virtual PC running Win98 and IE6: Internet Explorer crashed again when we hovered over one of the links with a:hover CSS styles.
&lt;/p&gt;
&lt;p&gt;
The solution to this problem was simply to apply a style to the hovered link (.hover). Then we could easily style the children of this element to our liking without breaking IE6.
&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
$(&lt;span class="str"&gt;&amp;quot;.FrontMenu .Bar a&amp;quot;&lt;/span&gt;).mouseover(&lt;span class="kwrd"&gt;function&lt;/span&gt;() { $(&lt;span class="kwrd"&gt;this&lt;/span&gt;).addClass(&lt;span class="str"&gt;&amp;quot;hover&amp;quot;&lt;/span&gt;); });
&lt;/pre&gt;
&lt;pre&gt;
$(&lt;span class="str"&gt;&amp;quot;.FrontMenu .Bar a&amp;quot;&lt;/span&gt;).mouseout(&lt;span class="kwrd"&gt;function&lt;/span&gt;() { $(&lt;span class="kwrd"&gt;this&lt;/span&gt;).removeClass(&lt;span class="str"&gt;&amp;quot;hover&amp;quot;&lt;/span&gt;); });
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
To change the style of the selected item we added the css class .sel to the span.item (the parent of the clicked link).&amp;nbsp; First of all, when a link is clicked, remove the currently selected item.&amp;nbsp; Second, set the parent of the link as the current selected item.&amp;nbsp; It&amp;rsquo;s important to return false as otherwise the browser will follow the link and scroll to the top of the page.
&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
$(&lt;span class="str"&gt;&amp;quot;div.FrontMenu div.Bar a&amp;quot;&lt;/span&gt;).click(function()
&lt;/pre&gt;
&lt;pre&gt;
{
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    $(&lt;span class="str"&gt;&amp;quot;div.FrontMenu div.Bar&amp;quot;&lt;/span&gt;).children(&lt;span class="str"&gt;&amp;quot;span.sel&amp;quot;&lt;/span&gt;).removeClass(&lt;span class="str"&gt;&amp;quot;sel&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre&gt;
    $(&lt;span class="kwrd"&gt;this&lt;/span&gt;).parent().addClass(&lt;span class="str"&gt;&amp;quot;sel&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre&gt;
});
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;h3&gt;CSS&lt;/h3&gt;
&lt;p&gt;
Let&amp;rsquo;s take a deeper look at the menu&amp;rsquo;s CSS.&amp;nbsp; Let&amp;rsquo;s start with the FirstMenu class which is not too complicated.
&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
.FrontMenu
&lt;/pre&gt;
&lt;pre&gt;
{
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    padding: 5px 5px 0px 5px;
&lt;/pre&gt;
&lt;pre&gt;
    margin-left: 2px;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    margin-top: -4px;
&lt;/pre&gt;
&lt;pre&gt;
}
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
.FrontMenu .Bar
&lt;/pre&gt;
&lt;pre class="alt"&gt;
{
&lt;/pre&gt;
&lt;pre&gt;
    background: #F6ECA4 url(images/MainPage/bar.jpg) no-repeat top left;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    width: 980px;
&lt;/pre&gt;
&lt;pre&gt;
    height: 48px;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    position: relative;
&lt;/pre&gt;
&lt;pre&gt;
}
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
.FrontMenu .Bar a
&lt;/pre&gt;
&lt;pre class="alt"&gt;
{
&lt;/pre&gt;
&lt;pre&gt;
    color: #FFFFFF;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    font-size: large;
&lt;/pre&gt;
&lt;pre&gt;
    font-family: Tahoma;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    position: relative;
&lt;/pre&gt;
&lt;pre&gt;
    top: 7px;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    display: block;
&lt;/pre&gt;
&lt;pre&gt;
    text-decoration: none;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    padding-right: 6px;
&lt;/pre&gt;
&lt;pre&gt;
    margin-right: -6px;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    cursor: pointer;
&lt;/pre&gt;
&lt;pre&gt;
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Now let&amp;rsquo;s take a closer look at the Bar menu.&amp;nbsp; Here are the images we used to style our menu items.
&lt;/p&gt;
&lt;table border="1" cellspacing="0" cellpadding="2" width="802"&gt;
	&lt;tbody&gt;
		&lt;tr&gt;
			&lt;td width="231"&gt;&lt;strong&gt;&lt;u&gt;CSS&lt;/u&gt;&lt;/strong&gt;&lt;/td&gt;
			&lt;td width="269"&gt;&lt;strong&gt;&lt;u&gt;Images&lt;/u&gt;&lt;/strong&gt;&lt;/td&gt;
			&lt;td width="126"&gt;&amp;nbsp;&lt;/td&gt;
			&lt;td width="174"&gt;&amp;nbsp;&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td width="230"&gt;.FrontMenu .Bar span.sel&lt;/td&gt;
			&lt;td width="269"&gt;
			&lt;p&gt;
			&lt;u&gt;selLeft.gif&lt;/u&gt;
			&lt;/p&gt;
			&lt;p&gt;
			&lt;a href="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/selLeft_2.gif"&gt;&lt;img src="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/selLeft_thumb.gif" border="0" alt="selLeft" title="selLeft" width="195" height="47" /&gt;&lt;/a&gt; 
			&lt;/p&gt;
			&lt;/td&gt;
			&lt;td width="129"&gt;
			&lt;p&gt;
			&lt;u&gt;selRight.gif&lt;/u&gt;
			&lt;/p&gt;
			&lt;p&gt;
			&lt;a href="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/selRight_2.gif"&gt;&lt;img src="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/selRight_thumb.gif" border="0" alt="selRight" title="selRight" width="5" height="47" /&gt;&lt;/a&gt; 
			&lt;/p&gt;
			&lt;/td&gt;
			&lt;td width="173"&gt;
			&lt;p&gt;
			&lt;u&gt;spike.gif&lt;/u&gt;
			&lt;/p&gt;
			&lt;p&gt;
			&lt;a href="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/spike_2.gif"&gt;&lt;img src="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/spike_thumb.gif" border="0" alt="spike" title="spike" width="22" height="17" /&gt;&lt;/a&gt; 
			&lt;/p&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td width="228"&gt;.FrontMenu .Bar a.hover span&lt;/td&gt;
			&lt;td width="269"&gt;
			&lt;p&gt;
			&lt;u&gt;hoverLeft.gif&lt;/u&gt;
			&lt;/p&gt;
			&lt;p&gt;
			&lt;a href="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/hoverLeft_2.gif"&gt;&lt;img src="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/hoverLeft_thumb.gif" border="0" alt="hoverLeft" title="hoverLeft" width="191" height="30" /&gt;&lt;/a&gt; 
			&lt;/p&gt;
			&lt;/td&gt;
			&lt;td width="132"&gt;
			&lt;p&gt;
			&lt;u&gt;hoverRight.gif&lt;/u&gt;
			&lt;/p&gt;
			&lt;p&gt;
			&amp;nbsp;
			&lt;/p&gt;
			&lt;p&gt;
			&amp;nbsp;
			&lt;/p&gt;
			&lt;p&gt;
			&lt;a href="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/hoverRight_2.gif"&gt;&lt;img src="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/hoverRight_thumb.gif" border="0" alt="hoverRight" title="hoverRight" width="6" height="30" /&gt;&lt;/a&gt; 
			&lt;/p&gt;
			&lt;/td&gt;
			&lt;td width="173"&gt;&amp;nbsp;&lt;/td&gt;
		&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
Like you saw in the jQuery part, we change the class in JavaScript to bypass some IE6 issues, so you should not be surprised by the CSS. 
&lt;/p&gt;
&lt;p&gt;
The code for the main span for each menu item:
&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
.FrontMenu .Bar span.item
&lt;/pre&gt;
&lt;pre&gt;
{
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    line-height: 30px;
&lt;/pre&gt;
&lt;pre&gt;
    margin: 0px 0px;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    float: left;
&lt;/pre&gt;
&lt;pre&gt;
    position: relative;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    display: inline;
&lt;/pre&gt;
&lt;pre&gt;
    cursor: pointer;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    width: 188px;
&lt;/pre&gt;
&lt;pre&gt;
    text-align: center;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    margin-left: 6px;
&lt;/pre&gt;
&lt;pre&gt;
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Here is the code when you hover over the link inside the menu item:
&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
/* We have to handle hover with jQuery because :hover makes IE6 crash when we change the background image. */
&lt;/pre&gt;
&lt;pre&gt;
.FrontMenu .Bar a.hover
&lt;/pre&gt;
&lt;pre class="alt"&gt;
{
&lt;/pre&gt;
&lt;pre&gt;
    background: transparent url(images/MainPage/hoverRight.gif) no-repeat top right;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    height: 30px;
&lt;/pre&gt;
&lt;pre&gt;
}
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
/* We have to handle hover with jQuery because :hover makes IE6 crash when we change the background image. */
&lt;/pre&gt;
&lt;pre class="alt"&gt;
.FrontMenu .Bar a.hover span
&lt;/pre&gt;
&lt;pre&gt;
{
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    background: transparent url(images/MainPage/hoverLeft.gif) no-repeat top left;
&lt;/pre&gt;
&lt;pre&gt;
    height: 30px;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    display: block;
&lt;/pre&gt;
&lt;pre&gt;
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Like you can see, the link contains the &lt;a href="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/hoverLeft_2.gif"&gt;&lt;img src="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/hoverLeft_thumb.gif" border="0" alt="hoverLeft" title="hoverLeft" width="191" height="30" /&gt;&lt;/a&gt;&amp;nbsp; background image and the span inside the link contains the &lt;a href="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/hoverRight_2.gif"&gt;&lt;img src="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/hoverRight_thumb.gif" border="0" alt="hoverRight" title="hoverRight" width="6" height="30" /&gt;&lt;/a&gt;.&amp;nbsp; This enables the link to have any length and the control will resize easily.&amp;nbsp; If you ever get a link that is wider than the left image, simply make the image wider...
&lt;/p&gt;
&lt;p&gt;
Then we only needed the CSS to change the menu item to make it look selected.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
.FrontMenu .Bar span.sel a:hover { background: none; padding-left: 0px; margin-left: 0px; }
&lt;/pre&gt;
&lt;pre&gt;
.FrontMenu .Bar span.sel a:hover span { background: none; padding-left: 0px; margin-left: 0px; }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
.FrontMenu .Bar span.sel
&lt;/pre&gt;
&lt;pre class="alt"&gt;
{
&lt;/pre&gt;
&lt;pre&gt;
    background: transparent url(images/MainPage/selLeft.gif) no-repeat top left;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    height: 48px;
&lt;/pre&gt;
&lt;pre&gt;
}
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
.FrontMenu .Bar span.item .spike, .FrontMenu .Bar span.sel .spike
&lt;/pre&gt;
&lt;pre class="alt"&gt;
{
&lt;/pre&gt;
&lt;pre&gt;
    background: transparent url(images/MainPage/spike.gif) no-repeat top left;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    display:none;
&lt;/pre&gt;
&lt;pre&gt;
    position: absolute;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    top: 44px;
&lt;/pre&gt;
&lt;pre&gt;
    left: 50%;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    margin-left: -11px;
&lt;/pre&gt;
&lt;pre&gt;
    width: 22px;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    height: 17px;
&lt;/pre&gt;
&lt;pre&gt;
    z-index: 9999;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
}
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
.FrontMenu .Bar span.sel .spike
&lt;/pre&gt;
&lt;pre&gt;
{
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    display: block;
&lt;/pre&gt;
&lt;pre&gt;
}
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
.FrontMenu .Bar span.sel .right
&lt;/pre&gt;
&lt;pre class="alt"&gt;
{
&lt;/pre&gt;
&lt;pre&gt;
    background: transparent url(images/MainPage/selRight.gif) no-repeat top right;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    position: absolute;
&lt;/pre&gt;
&lt;pre&gt;
    height: 48px;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    width: 4px;
&lt;/pre&gt;
&lt;pre&gt;
    right: 0px;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    top: 0px;
&lt;/pre&gt;
&lt;pre&gt;
}
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
.FrontMenu .Bar span.sel a { color: #d43300; }
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
The parent span for the menu item with the .sel class contains the &lt;a href="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/selLeft_2.gif"&gt;&lt;img src="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/selLeft_thumb.gif" border="0" alt="selLeft" title="selLeft" width="195" height="47" /&gt;&lt;/a&gt; image and the div.right inside this span contains the &lt;a href="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/selRight_2.gif"&gt;&lt;img src="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/selRight_thumb.gif" border="0" alt="selRight" title="selRight" width="5" height="47" /&gt;&lt;/a&gt; image.&amp;nbsp; We have to make sure too that the hover style does not get applied when the item is selected.
&lt;/p&gt;
&lt;p&gt;
The spike &lt;a href="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/spike_2.gif"&gt;&lt;img src="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/LavaBlastFrontPageMenu_AB60/spike_thumb.gif" border="0" alt="spike" title="spike" width="22" height="17" /&gt;&lt;/a&gt; is applied in absolute position in the center.&amp;nbsp; To do that in absolute position, you have to set the following:
&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
left: 50%;
&lt;/pre&gt;
&lt;pre&gt;
margin-left: -11px;  // &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&amp;mdash;This is the width/2
&lt;/pre&gt;
&lt;pre class="alt"&gt;
width: 22px;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Even with a higher z-index, we were not able to make the spike go on top of the content panel in IE6.&amp;nbsp; Therefore, we had to put a margin on top of content panel just to make sure the spike was not overlapping the content panel below:
&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
.FrontMenu div.Panel
&lt;/pre&gt;
&lt;pre&gt;
{
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    height: 328px;
&lt;/pre&gt;
&lt;pre&gt;
    width: 974px;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    margin-top: 15px;
&lt;/pre&gt;
&lt;pre&gt;
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.lavablast.com/SliderMenu/"&gt;Simple Demo (Firefox, IE7, IE6, Opera, Safari)&lt;/a&gt; | &lt;a href="http://www.lavablast.com"&gt;Demo with content&lt;/a&gt; | &lt;a href="http://blog.lavablast.com/uploads/SliderMenu.zip"&gt;Source Code&lt;/a&gt;
&lt;/p&gt;
&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblog.lavablast.com%2fpost%2f2008%2f07%2fjQuery-Content-Slider-Tutorial.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblog.lavablast.com%2fpost%2f2008%2f07%2fjQuery-Content-Slider-Tutorial.aspx&amp;amp;border=660000&amp;amp;fgcolor=660000&amp;amp;bgcolor=FF9900&amp;amp;cbgcolor=FFFF00" border="0" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;
</description>
      <link>http://feeds.feedburner.com/~r/LavablastSoftwareBlog/~3/342847997/post.aspx</link>
      <author>EtienneT</author>
      <comments>http://blog.lavablast.com/post/2008/07/jQuery-Content-Slider-Tutorial.aspx#comment</comments>
      <guid isPermaLink="false">http://blog.lavablast.com/post.aspx?id=e3197848-44f4-4b3f-b29c-f97d5e43ac3b</guid>
      <pubDate>Tue, 22 Jul 2008 15:22:00 -0400</pubDate>
      <category>Design</category>
      <category>Software</category>
      <dc:publisher>EtienneT</dc:publisher>
      <pingback:server>http://blog.lavablast.com/pingback.axd</pingback:server>
      <pingback:target>http://blog.lavablast.com/post.aspx?id=e3197848-44f4-4b3f-b29c-f97d5e43ac3b</pingback:target>
      <slash:comments>19</slash:comments>
      <trackback:ping>http://blog.lavablast.com/trackback.axd?id=e3197848-44f4-4b3f-b29c-f97d5e43ac3b</trackback:ping>
      <wfw:comment>http://blog.lavablast.com/post/2008/07/jQuery-Content-Slider-Tutorial.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.lavablast.com/syndication.axd?post=e3197848-44f4-4b3f-b29c-f97d5e43ac3b</wfw:commentRss>
    <feedburner:origLink>http://blog.lavablast.com/post.aspx?id=e3197848-44f4-4b3f-b29c-f97d5e43ac3b</feedburner:origLink></item>
    <item>
      <title>Would you put cartoons on your software startup's website?</title>
      <description>&lt;p&gt;
We&amp;#39;ve revamped our &lt;a href="http://www.lavablast.com"&gt;website home page&lt;/a&gt; and wanted to invite you to visit it and let us know what you think.&amp;nbsp;&amp;nbsp; The general template of the site hasn&amp;#39;t changed, as our enhancements focused on five core elements:
&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;&lt;strong&gt;Simpler menu structure&lt;/strong&gt;. When we first launched our website, our pages were never nested more than one level deep. We&amp;#39;ve since added new content and our site was getting harder to navigate. By going with a tree-like structure and adding markers to indicate which page you are currently viewing, we feel this solves our main usability problem. &lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Testimonials. &lt;/strong&gt;Ian Graham, the man behind &lt;a href="http://www.thecodefactory.ca"&gt;The Code Factory, an Ottawa-based software co-working location&lt;/a&gt;, talks about how he &lt;a href="http://www.lavablast.com/en/lb_testimonials.aspx"&gt;enjoyed doing business with us&lt;/a&gt;. We feel this touch increases our credibility, and the fact that we get things done.&amp;nbsp; &lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Concise information. &lt;/strong&gt;We&amp;#39;ve integrated much more information on our home page and re-worked the text to make it very concise. The home page leads you to numerous inner pages which feature more detailed information about our products. We&amp;#39;re always re-working the innards of our site and we&amp;#39;re never &amp;quot;done&amp;quot;, but we feel this new home page will help drive traffic to the appropriate locations.... only &lt;strike&gt;time&lt;/strike&gt; &lt;a href="http://www.google.com/analytics"&gt;Google Analytics&lt;/a&gt; will tell. &lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Web 2.0 slider.&lt;/strong&gt; We wanted to have a bit of fun even if it meant &lt;a href="http://blog.lavablast.com/post/2007/11/In-20072c-can-we-afford-to-refuse-potential-customers-who-done28099t-have-JavaScript-enabled.aspx"&gt;requiring JavaScript on our pages&lt;/a&gt;. &lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Cartoons.&lt;/strong&gt; This is the most controversial aspect of our new home page. We&amp;#39;ve integrated cartoons on our homepage.... cartoons on a &lt;a href="http://www.lavablast.com"&gt;franchise software corporate site&lt;/a&gt;? Allow us to explain. &lt;/li&gt;
&lt;/ol&gt;
&lt;p style="text-align: center"&gt;
&lt;a href="http://www.lavablast.com"&gt;&lt;img style="border-width: 0px; margin: 10px" src="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/Atouchofstyle_9022/homepage_3.jpg" border="0" alt="LavaBlast Software home page" width="644" height="390" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;h2&gt;Why are we using cartoons? &lt;/h2&gt;
&lt;p&gt;
Simply put, everyone we&amp;#39;ve talked to is divided in two completely distinct camps. One camp feels our cartoons makes our website unprofessional and inappropriate for the franchise industry&amp;#39;s decision makers (one of the more vocal people in this camp is &lt;a href="http://www.bizop.ca"&gt;Michael Webster, Ph.D, LL.B&lt;/a&gt;.). Others feel it gives us a more personalized feel (a human touch) which increases their trust in our company. 
&lt;/p&gt;
&lt;p&gt;
There are hundreds of companies building software for the franchise industry and we want to show that we have a different philosophy from many of the old-school companies. Simply put, we (as web visitors) distrust generic consulting websites littered with stock photography and we didn&amp;#39;t want to repeat the same mistake. We love to use pictures, but bad quality pictures or video are often worse than not having any.&amp;nbsp; After a year and a half of having a more corporate feel (without using stock photography), we decided it was time to do something wilder. We hope to impress our target market with an atypical corporate website, even if it ruffles a few feathers.&amp;nbsp;&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
We target &lt;strong&gt;small yet energetic franchise systems&lt;/strong&gt;. These franchisors are not heads of billion dollar corporate empires, they are entrepreneurs who want to grow a concept which worked in their flagship store and scale it to the next level, via franchising. At their growth stage, these franchisors are looking for someone who can listen to their needs, build cost-effective software solutions, and help them grow. The franchises we deal with don&amp;#39;t have large IT departments: they&amp;#39;re looking to get outside help with technology, as they don&amp;#39;t have the knowledge in-house. Outsourcing allows them to get more bang for their buck than hiring software engineers to build everything from scratch.
&lt;/p&gt;
&lt;h2&gt;Why don&amp;#39;t you like stock photos?&lt;/h2&gt;
&lt;p&gt;
&lt;strong&gt;Does the following image incite you to contact a software firm for custom development?&lt;/strong&gt;
&lt;/p&gt;
&lt;p style="text-align: center"&gt;
&lt;a href="http://www.flickr.com/photos/aroberts/2282881973/"&gt;&lt;img style="border-width: 0px; margin: 10px" src="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/Atouchofstyle_9022/handshake_3.jpg" border="0" alt="handshake stock photo" width="180" height="136" /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
When we shop around and find a company featuring such a picture, it reveals that they botched their web development work and they&amp;#39;re probably going to botch any work we give them. Attention to detail is one characteristic we always want to see; however, we&amp;#39;re not completely against stock photography but we disapprove of stock photography abuse. For example, if a company has a page talking about their team, and the team picture is actually a stock photo... they&amp;#39;re taking it too far. 
&lt;/p&gt;
&lt;p&gt;
As a sidenote, &lt;a href="http://www.ideeinc.com"&gt;Toronto-based Id&amp;eacute;e Inc&lt;/a&gt;. created an &lt;a href="http://www.tineye.com"&gt;image search engine&lt;/a&gt; that not only helps identify stock photography but also people that have stolen your copyrighted images. Here&amp;#39;s a screenshot of the results returned by &lt;a href="http://www.tineye.com"&gt;TinEye&lt;/a&gt; for the previous image:&amp;nbsp; 
&lt;/p&gt;
&lt;p style="text-align: center"&gt;
&lt;a href="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/Atouchofstyle_9022/tineye_5.jpg"&gt;&lt;img style="border-width: 0px" src="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/Atouchofstyle_9022/tineye_thumb_1.jpg" border="0" alt="TinEye Image Search" width="544" height="532" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.tineye.com"&gt;TinEye&lt;/a&gt; even found this modified image... very nice technology! 
&lt;/p&gt;
&lt;p style="text-align: center"&gt;
&lt;a href="http://www.tineye.com"&gt;&lt;img style="border-width: 0px" src="http://blog.lavablast.com/image.axd?picture=WindowsLiveWriter/Atouchofstyle_9022/handshake2_3.jpg" border="0" alt="modified handshake" width="129" height="76" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;h2&gt;What do you think?&lt;/h2&gt;
&lt;p&gt;
In summary, we decided to go with a cartoonish feel because we felt it was the best way to distinguish ourselves from our stereotypical competition. We purposefully project more youthful brand image, as we are targeting smaller franchise systems. Do you think differently? Are you an ardent defender of stock photo or do you think you&amp;#39;ve found the perfect balance of web 2.0 styling with the warm fuzzy feeling of seeing people? Do you agree with us? Let us know! 
&lt;/p&gt;
&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblog.lavablast.com%2fpost%2f2008%2f07%2fWould-you-put-cartoons-on-your-software-startups-website.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblog.lavablast.com%2fpost%2f2008%2f07%2fWould-you-put-cartoons-on-your-software-startups-website.aspx&amp;amp;border=660000&amp;amp;fgcolor=660000&amp;amp;bgcolor=FF9900&amp;amp;cbgcolor=FFFF00" border="0" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://news.lavablast.com/blast/?url=http%3a%2f%2fblog.lavablast.com%2fpost%2f2008%2f07%2fWould-you-put-cartoons-on-your-software-startups-website.aspx"&gt;&lt;img src="http://news.lavablast.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblog.lavablast.com%2fpost%2f2008%2f07%2fWould-you-put-cartoons-on-your-software-startups-website.aspx&amp;amp;fgcolor=ffffff" border="0" alt="blast it on Franchise NewsBlast" /&gt;&lt;/a&gt;
</description>
      <link>http://feeds.feedburner.com/~r/LavablastSoftwareBlog/~3/341566665/post.aspx</link>
      <author>JKealey</author>
      <comments>http://blog.lavablast.com/post/2008/07/Would-you-put-cartoons-on-your-software-startups-website.aspx#comment</comments>
      <guid isPermaLink="false">http://blog.lavablast.com/post.aspx?id=df24727a-44db-4453-aee1-a436c3490cd9</guid>
      <pubDate>Thu, 17 Jul 2008 20:42:00 -0400</pubDate>
      <category>General</category>
      <category>News</category>
      <dc:publisher>JKealey</dc:publisher>
      <pingback:server>http://blog.lavablast.com/pingback.axd</pingback:server>
      <pingback:target>http://blog.lavablast.com/post.aspx?id=df24727a-44db-4453-aee1-a436c3490cd9</pingback:target>
      <slash:comments>13</slash:comments>
      <trackback:ping>http://blog.lavablast.com/trackback.axd?id=df24727a-44db-4453-aee1-a436c3490cd9</trackback:ping>
      <wfw:comment>http://blog.lavablast.com/post/2008/07/Would-you-put-cartoons-on-your-software-startups-website.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.lavablast.com/syndication.axd?post=df24727a-44db-4453-aee1-a436c3490cd9</wfw:commentRss>
    <feedburner:origLink>http://blog.lavablast.com/post.aspx?id=df24727a-44db-4453-aee1-a436c3490cd9</feedburner:origLink></item>
    <item>
      <title>Image Post Processing Caching</title>
      <description>&lt;p&gt;
&lt;a href="http://blog.lavablast.com/uploads/ImageCacheManager.zip"&gt;Complete Source Code&lt;/a&gt; | &lt;a href="http://blog.lavablast.com/ImageCacheManager/default.aspx"&gt;Small Demo&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
This article present a small class library that abstracts opening, modifying (applying effects, resizing, etc.), and caching images in ASP.NET.&amp;nbsp; Everything needs to be abstracted to ensure the code is easily testable (opening, modifying, and caching of the images).&amp;nbsp; You may want to resize your images or convert them to black and white and cache the result, and want to test these operations.
&lt;/p&gt;
&lt;p&gt;
You want to be able to read image data from different sources:
&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;An image on the local disk on the web server &lt;/li&gt;    
	&lt;li&gt;A remote image on the Internet that you want to download and cache &lt;/li&gt;    
	&lt;li&gt;An image in your database &lt;/li&gt; 
&lt;/ul&gt;
&lt;p&gt;
You want to be able to apply any number of post processing algorithms to the resulting image:
&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Resize the image (generate thumbnails) &lt;/li&gt;    
	&lt;li&gt;Apply an image filter such as convert to black and white &lt;/li&gt;    
	&lt;li&gt;Do anything on the image that requires computing and where caching the result proves beneficial from a performance standpoint.&amp;nbsp; &lt;/li&gt; 
&lt;/ul&gt;
&lt;h2&gt;CacheManager&lt;/h2&gt;  
&lt;p&gt;
First of all, let&amp;#39;s look at a nice caching class I found on a &lt;a href="http://www.dotnetkicks.com"&gt;DotNetKicks&lt;/a&gt; kicked story.&amp;nbsp; &lt;a href="http://weblogs.asp.net/zowens/default.aspx"&gt;Zack Owens&lt;/a&gt; gave a &lt;a href="http://weblogs.asp.net/zowens/archive/2007/10/20/easier-way-to-manage-your-asp-net-cache.aspx"&gt;nice piece of code&lt;/a&gt; in his blog to help you manage your ASP.NET cached objects.&amp;nbsp; The goal of this class is simply to let you have a strongly typed way to access your cached objects.&amp;nbsp; Here is the code for the class with some slight modifications:
&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CacheManager&amp;lt;T&amp;gt; &lt;span class="kwrd"&gt;where&lt;/span&gt; T : &lt;span class="kwrd"&gt;class&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
{
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; Cache cache;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; CacheItemRemovedCallback callback;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt; _lock = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;();
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; TimeSpan cacheTime = &lt;span class="kwrd"&gt;new&lt;/span&gt; TimeSpan(1, 0, 0, 0); &lt;span class="rem"&gt;// Default 1 day&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; CacheManager(Cache cache)
&lt;/pre&gt;
&lt;pre&gt;
    {
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.cache = cache;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;if&lt;/span&gt;(callback == &lt;span class="kwrd"&gt;null&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            callback = &lt;span class="kwrd"&gt;new&lt;/span&gt; CacheItemRemovedCallback(RemovedFromCache);
&lt;/pre&gt;
&lt;pre&gt;
    }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; T Get(&lt;span class="kwrd"&gt;string&lt;/span&gt; key)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    {
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;try&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        {
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;lock&lt;/span&gt; (_lock)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            {
&lt;/pre&gt;
&lt;pre&gt;
                &lt;span class="kwrd"&gt;if&lt;/span&gt; (cache[key] == &lt;span class="kwrd"&gt;null&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;default&lt;/span&gt;(T);
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                T b = CastToT(cache[key]);
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                &lt;span class="kwrd"&gt;return&lt;/span&gt; b;
&lt;/pre&gt;
&lt;pre&gt;
            }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        }
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;catch&lt;/span&gt; (ArgumentException ex) &lt;span class="rem"&gt;// The object was disposed by something! return null;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        {
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;null&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        }
&lt;/pre&gt;
&lt;pre&gt;
    }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Add(&lt;span class="kwrd"&gt;string&lt;/span&gt; key, T obj, TimeSpan cacheTime)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    {
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;lock&lt;/span&gt; (_lock)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        {
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (obj != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                cache.Add(key, CastFromT(obj), &lt;span class="kwrd"&gt;null&lt;/span&gt;, DateTime.Now.Add(cacheTime), Cache.NoSlidingExpiration, CacheItemPriority.Default, callback);
&lt;/pre&gt;
&lt;pre&gt;
        }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    }
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; RemovedFromCache(&lt;span class="kwrd"&gt;string&lt;/span&gt; key, &lt;span class="kwrd"&gt;object&lt;/span&gt; o, CacheItemRemovedReason reason)
&lt;/pre&gt;
&lt;pre&gt;
    {
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        T obj = o &lt;span class="kwrd"&gt;as&lt;/span&gt; T;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (obj != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        {
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;lock&lt;/span&gt; (_lock)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            {
&lt;/pre&gt;
&lt;pre&gt;
                DisposeObject(obj);
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            }
&lt;/pre&gt;
&lt;pre&gt;
        }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    }
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; DisposeObject(T obj) { }
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; T CastToT(&lt;span class="kwrd"&gt;object&lt;/span&gt; obj) { &lt;span class="kwrd"&gt;return&lt;/span&gt; obj &lt;span class="kwrd"&gt;as&lt;/span&gt; T; }
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt; CastFromT(T obj) { &lt;span class="kwrd"&gt;return&lt;/span&gt; obj &lt;span class="kwrd"&gt;as&lt;/span&gt; T; }
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; TimeSpan CacheTime
&lt;/pre&gt;
&lt;pre&gt;
    {
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; cacheTime; }
&lt;/pre&gt;
&lt;pre&gt;
        set { cacheTime = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    }
&lt;/pre&gt;
&lt;pre&gt;
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
As you can see, this is a pretty simple class.&amp;nbsp; We defined some virtual methods to be implemented in our child class, for example DisposeObject if you want to cache disposable objects (continue to read if you want to know why this is a really bad idea).
&lt;/p&gt;
&lt;p&gt;
The constructor requires a Cache object; we can simply pass along the Page&amp;#39;s Cache (Page.Cache) to make it happy.&amp;nbsp; We now want to derive from CacheManager to help us in our main task which is to cache modified images.
&lt;/p&gt;
&lt;h2&gt;ImageCacheManager&lt;/h2&gt;
&lt;p&gt;
To create our image-specific cache manager, we defined a new class called ImageCacheManager which is a subclass of CacheManager&amp;nbsp; and will cache byte arrays (our images).&amp;nbsp; We implemented this feature in the past, but did a big mistake that led to a &lt;a href="http://blog.lavablast.com/post/2007/11/The-Mysterious-Parameter-Is-Not-Valid-Exception.aspx"&gt;mysterious bug&lt;/a&gt;.&amp;nbsp; We were caching Bitmap objects in the ASP.NET cache but this was a big, big mistake.&amp;nbsp; Bitmap objects are GDI+ managed objects and they need to get disposed.&amp;nbsp; Even if we had methods to dispose the Bitmap when they were removed from the cache, some Bitmap objects were disposed while still in the cache (because of a memory leak elsewhere in the application). This caused errors downstream when we tried to use those objects later.&amp;nbsp; The lesson: we&amp;#39;ll only cache only byte[] of the images.
&lt;/p&gt;
&lt;p&gt;
The default image format is PNG in our case, but you can specify your own in the constructor.&amp;nbsp; In our case we are using PNG because we are in a controlled environment where we know everyone is using IE7, so we can use transparent PNG.&amp;nbsp; You probably want to use a different format for general public web sites since IE6 doesn&amp;#39;t support transparent PNG.
&lt;/p&gt;
&lt;p&gt;
This class will enable to download remote images and cache them locally, as well.&amp;nbsp; We needed this feature since we have a lot of &lt;a href="http://www.lavablast.com/en/lb_pointofsale.aspx"&gt;remote point of sales&lt;/a&gt; which &lt;a href="http://www.lavablast.com/en/lb_franchiseblast.aspx"&gt;synchronize their product list from a central database&lt;/a&gt;.&amp;nbsp; We didn&amp;#39;t want to send product images during synchronization because it would have been too much data.&amp;nbsp; Instead we decided to store our images on a central server and since our stores always have Internet access, they download and cache the images via this image cache manager.&amp;nbsp; In our product, when a &lt;a href="http://www.lavablast.com/en/lb_franchiseblast.aspx"&gt;franchisor changes a product image in the main database&lt;/a&gt;, the cached version of the picture in the &lt;a href="http://www.lavablast.com/en/lb_pointofsale.aspx"&gt;point of sale&lt;/a&gt; will expire within the next day and the new picture would be downloaded when used.
&lt;/p&gt;
&lt;p&gt;
ImageCacheManager is an abstract class.&amp;nbsp; It implements image caching and handles the fact that you want to apply post processing to an image with options (interface IImagePostProcess) and it abstracts the way you load the image (interface IImageReader).&amp;nbsp; Here is the code:
&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Text;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.Caching;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Drawing;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.IO;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Drawing.Drawing2D;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Drawing.Imaging;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Net;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; LavaBlast.ImageCaching.PostProcess;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; LavaBlast.ImageCaching.Reader;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;namespace&lt;/span&gt; LavaBlast.ImageCaching
&lt;/pre&gt;
&lt;pre class="alt"&gt;
{
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="rem"&gt;/// This class specialize in caching modified images.  Images are cached as&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="rem"&gt;/// byte[].  You can apply different modifications in serial to the image&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="rem"&gt;/// before caching it.&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="rem"&gt;/// &lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="rem"&gt;/// Construct a cache key depending on the options of your image post processing.&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="rem"&gt;/// This enables to cache copies of an image with different post processing applied to it.&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="rem"&gt;/// &lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="rem"&gt;/// Control how the image will be read.  On local disk, via Internet etc.&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;abstract&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ImageCacheManager : CacheManager&amp;lt;&lt;span class="kwrd"&gt;byte&lt;/span&gt;[]&amp;gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    {
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; ImageCacheManager(Cache cache) : &lt;span class="kwrd"&gt;this&lt;/span&gt;(cache, ImageFormat.Png) { }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;protected&lt;/span&gt; Dictionary&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, IImagePostProcess&amp;gt; postProcess = &lt;span class="kwrd"&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, IImagePostProcess&amp;gt;();
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;protected&lt;/span&gt; ImageFormat format = ImageFormat.Png; &lt;span class="rem"&gt;// Default image format PNG&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; ImageCacheManager(Cache cache, ImageFormat format) : &lt;span class="kwrd"&gt;base&lt;/span&gt;(cache)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        {
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;this&lt;/span&gt;.format = format;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
            InitImagePostProcess();
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        }
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="rem"&gt;/// Determine which image reader will be used to read this image.&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="rem"&gt;/// &amp;lt;param name=&amp;quot;uriPath&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;abstract&lt;/span&gt; IImageReader GetReader(Uri uriPath);
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/// Fill the variable postProcess with post processing to apply&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="rem"&gt;/// to an image each time.&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;abstract&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; InitImagePostProcess();
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/// This method shall return a unique key depending on the path of the&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="rem"&gt;/// image plus the options of it&amp;#39;s post processing process.&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="rem"&gt;/// &amp;lt;param name=&amp;quot;path&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/// &amp;lt;param name=&amp;quot;options&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;abstract&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ConstructKey(Uri path, Dictionary&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;object&lt;/span&gt;&amp;gt; options);
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="rem"&gt;/// Get an image from the following path.  Use the provided options to use in post processing.&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/// If refresh is true, don&amp;#39;t use the cached version.&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/// &amp;lt;param name=&amp;quot;uriPath&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="rem"&gt;/// &amp;lt;param name=&amp;quot;options&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/// &amp;lt;param name=&amp;quot;refresh&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] GetImage(Uri uriPath, Dictionary&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;object&lt;/span&gt;&amp;gt; options, &lt;span class="kwrd"&gt;bool&lt;/span&gt; refresh)
&lt;/pre&gt;
&lt;pre&gt;
        {
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            &lt;span class="kwrd"&gt;string&lt;/span&gt; key = ConstructKey(uriPath, options);
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] cached = Get(key);
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (cached != &lt;span class="kwrd"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; !refresh)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                &lt;span class="kwrd"&gt;return&lt;/span&gt; cached;
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;else&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            {
&lt;/pre&gt;
&lt;pre&gt;
                &lt;span class="kwrd"&gt;try&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                {
&lt;/pre&gt;
&lt;pre&gt;
                    &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] image = ReadBitmap(uriPath); &lt;span class="rem"&gt;// Get the original data from the image&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
                    &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] modified = PostProcess(image, options); &lt;span class="rem"&gt;// Do any post processing on the image (resize it or apply some effects)&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
                    Add(key, modified, CacheTime); &lt;span class="rem"&gt;// Add this modified version to the cache&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
                    &lt;span class="kwrd"&gt;return&lt;/span&gt; modified;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                }
&lt;/pre&gt;
&lt;pre&gt;
                &lt;span class="kwrd"&gt;catch&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                {
&lt;/pre&gt;
&lt;pre&gt;
                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;null&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                }
&lt;/pre&gt;
&lt;pre&gt;
            }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        }
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="rem"&gt;/// Run all post processing process on the image and return the resulting image.&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="rem"&gt;/// &amp;lt;param name=&amp;quot;input&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/// &amp;lt;param name=&amp;quot;options&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] PostProcess(&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] input, Dictionary&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;object&lt;/span&gt;&amp;gt; options)
&lt;/pre&gt;
&lt;pre&gt;
        {
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] result = input;
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt; key &lt;span class="kwrd"&gt;in&lt;/span&gt; postProcess.Keys)
&lt;/pre&gt;
&lt;pre&gt;
                result = postProcess[key].Process(result, options[key]);
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;return&lt;/span&gt; result;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        }
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="rem"&gt;/// From a path, return a byte[] of the image.&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="rem"&gt;/// &amp;lt;param name=&amp;quot;uriPath&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] ReadBitmap(Uri uriPath)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        {
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;using&lt;/span&gt; (Stream stream = GetReader(uriPath).GetData(uriPath))
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            {
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] data = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;byte&lt;/span&gt;[0];
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                Bitmap pict = &lt;span class="kwrd"&gt;null&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                &lt;span class="kwrd"&gt;try&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
                {
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                    pict = &lt;span class="kwrd"&gt;new&lt;/span&gt; Bitmap(stream);
&lt;/pre&gt;
&lt;pre&gt;
                    data = ImageHelper.GetBytes(pict, format);
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                }
&lt;/pre&gt;
&lt;pre&gt;
                &lt;span class="kwrd"&gt;catch&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                {
&lt;/pre&gt;
&lt;pre&gt;
                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;null&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                }
&lt;/pre&gt;
&lt;pre&gt;
                &lt;span class="kwrd"&gt;finally&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                {
&lt;/pre&gt;
&lt;pre&gt;
                    &lt;span class="kwrd"&gt;if&lt;/span&gt; (pict != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                        pict.Dispose();
&lt;/pre&gt;
&lt;pre&gt;
                }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
                stream.Close();
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
                &lt;span class="kwrd"&gt;return&lt;/span&gt; data;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            }
&lt;/pre&gt;
&lt;pre&gt;
        }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    }
&lt;/pre&gt;
&lt;pre&gt;
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Because this is an abstract base class, we need a concrete implementation of ImageCacheManager.&amp;nbsp; We created ThumbnailCacheManager.&amp;nbsp; ThumbnailCacheManager checks the URI if it&amp;rsquo;s a local or remote file and uses the right image reader.&amp;nbsp; It has only one post processing task (resizing the image), but it could have more.&amp;nbsp; It construct the unique key for the cache from the processing task&amp;rsquo;s options.
&lt;/p&gt;
&lt;h2&gt;Image Resizing&lt;/h2&gt;
&lt;p&gt;
Here is a quick example of a typical image processing task: resizing it.&amp;nbsp; The class implement the simple method Process(byte[] input, object op) where op is in fact the options of the post processing process.&amp;nbsp; I could not use generics in my IImagePostProcess interface because of the way I store them later&amp;hellip;&amp;nbsp; Here is a quick code example of how to resize an image.
&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;namespace&lt;/span&gt; LavaBlast.ImageCaching.PostProcess
&lt;/pre&gt;
&lt;pre&gt;
{
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="rem"&gt;/// Post processing that take an image and resize it&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ImageResizePostProcess : IImagePostProcess
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    {
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] Process(&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] input, &lt;span class="kwrd"&gt;object&lt;/span&gt; op)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        {
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] oThumbNail;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
            ImageResizeOptions options = (ImageResizeOptions)op;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
            Bitmap pict = &lt;span class="kwrd"&gt;null&lt;/span&gt;, thumb = &lt;span class="kwrd"&gt;null&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;try&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            {
&lt;/pre&gt;
&lt;pre&gt;
                &lt;span class="kwrd"&gt;using&lt;/span&gt; (MemoryStream s = &lt;span class="kwrd"&gt;new&lt;/span&gt; MemoryStream(input))
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                {
&lt;/pre&gt;
&lt;pre&gt;
                    pict = &lt;span class="kwrd"&gt;new&lt;/span&gt; Bitmap(s); &lt;span class="rem"&gt;// Initial picture&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
                    s.Close();
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                }
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                thumb = &lt;span class="kwrd"&gt;new&lt;/span&gt; Bitmap(options.Size.Width, options.Size.Height); &lt;span class="rem"&gt;// Future thumb picture&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                &lt;span class="kwrd"&gt;using&lt;/span&gt; (Graphics oGraphic = Graphics.FromImage(thumb))
&lt;/pre&gt;
&lt;pre&gt;
                {
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                    oGraphic.CompositingQuality = CompositingQuality.HighQuality;
&lt;/pre&gt;
&lt;pre&gt;
                    oGraphic.SmoothingMode = SmoothingMode.HighQuality;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                    oGraphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
&lt;/pre&gt;
&lt;pre&gt;
                    oGraphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                    Rectangle oRectangle = &lt;span class="kwrd"&gt;new&lt;/span&gt; Rectangle(0, 0, options.Size.Width, options.Size.Height);
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                    oGraphic.DrawImage(pict, oRectangle);
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                    oThumbNail = ImageHelper.GetBytes(thumb, options.ImageFormat);
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                    oGraphic.Dispose();
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                    &lt;span class="kwrd"&gt;return&lt;/span&gt; oThumbNail;
&lt;/pre&gt;
&lt;pre&gt;
                }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            }
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;catch&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            {
&lt;/pre&gt;
&lt;pre&gt;
                &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;null&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            }
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;finally&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            {
&lt;/pre&gt;
&lt;pre&gt;
                &lt;span class="kwrd"&gt;if&lt;/span&gt; (thumb != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                    thumb.Dispose();
&lt;/pre&gt;
&lt;pre&gt;
                &lt;span class="kwrd"&gt;if&lt;/span&gt; (pict != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                    pict.Dispose();
&lt;/pre&gt;
&lt;pre&gt;
            }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        }
&lt;/pre&gt;
&lt;pre&gt;
    }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ImageResizeOptions
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    {
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; Size Size = Size.Empty;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; ImageFormat ImageFormat = ImageFormat.Png;
&lt;/pre&gt;
&lt;pre&gt;
    }
&lt;/pre&gt;
&lt;pre class="alt"&gt;
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;h2&gt;Reading the picture&lt;/h2&gt;
&lt;p&gt;
Reading the picture is the easy part and I have included two implementations of IImageReader: one for a local images and one for a remote images.&amp;nbsp; You could easily implement one which loads images from you database.
&lt;/p&gt;
&lt;h3&gt;LocalImageReader&lt;/h3&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="rem"&gt;/// An image reader to read images on local disk.&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; LocalImageReader : IImageReader
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    {
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; Stream GetData(Uri path)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        {
&lt;/pre&gt;
&lt;pre&gt;
            FileStream stream = &lt;span class="kwrd"&gt;new&lt;/span&gt; FileStream(path.LocalPath, FileMode.Open);
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;return&lt;/span&gt; stream;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        }
&lt;/pre&gt;
&lt;pre&gt;
    }
&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;RemoteImageReader&lt;/h3&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="rem"&gt;/// Image reader to read remote image on the web.&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; RemoteImageReader : IImageReader
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    {
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; Stream GetData(Uri url)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        {
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;string&lt;/span&gt; path = url.ToString();
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            &lt;span class="kwrd"&gt;try&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
            {
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                &lt;span class="kwrd"&gt;if&lt;/span&gt; (path.StartsWith(&lt;span class="str"&gt;&amp;quot;~/&amp;quot;&lt;/span&gt;))
&lt;/pre&gt;
&lt;pre&gt;
                    path = &lt;span class="str"&gt;&amp;quot;file://&amp;quot;&lt;/span&gt; + HttpRuntime.AppDomainAppPath + path.Substring(2, path.Length - 2);
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
                WebRequest request = (WebRequest)WebRequest.Create(&lt;span class="kwrd"&gt;new&lt;/span&gt; Uri(path));
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
                WebResponse response = request.GetResponse() &lt;span class="kwrd"&gt;as&lt;/span&gt; WebResponse;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre&gt;
                &lt;span class="kwrd"&gt;return&lt;/span&gt; response.GetResponseStream();
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            }
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;catch&lt;/span&gt; { &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; MemoryStream(); } &lt;span class="rem"&gt;// Don&amp;#39;t make the program crash just because we have a picture which failed downloading&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        }
&lt;/pre&gt;
&lt;pre&gt;
    }
&lt;/pre&gt;
&lt;/div&gt;
&lt;h2&gt;HttpHandler&lt;/h2&gt;
&lt;p&gt;
Finally, you want to serve those images with an HttpHandler. The code for the HttpHandler is pretty simple as you only need to parse the parameters from the QueryString and pass them to the ThumbnailCacheManager presented above.&amp;nbsp; The handler receives a parameter &amp;ldquo;p&amp;rdquo; for the path of the image (local or remote) and a parameter &amp;ldquo;refresh&amp;rdquo; which can be used to ignore the cached version of the image.&amp;nbsp; Additionally, we can pass parameters such as &amp;ldquo;width&amp;rdquo; and &amp;ldquo;height&amp;rdquo; for our image resizing.&amp;nbsp; &lt;strong&gt;Warning: you must adapt this code to your environment otherwise you are exposing a security hole because of the path parameter. &lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
When debugging your image caching HttpHandler, don&amp;#39;t forget to clear your temporary Internet files from IE or FireFox because your images will also be cached in your web browser otherwise your code will not be executed!
&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Data;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.Services;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.Services.Protocols;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; LavaBlast.ImageCaching;
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
&lt;span class="kwrd"&gt;namespace&lt;/span&gt; WebApplication
&lt;/pre&gt;
&lt;pre&gt;
{
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="rem"&gt;/// Really simple HttpHandler to output an image.&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ImageCaching : IHttpHandler
&lt;/pre&gt;
&lt;pre class="alt"&gt;
    {
&lt;/pre&gt;
&lt;pre&gt;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ProcessRequest(HttpContext context)
&lt;/pre&gt;
&lt;pre class="alt"&gt;
        {
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;string&lt;/span&gt; path = context.Request.Params[&lt;span class="str"&gt;&amp;quot;p&amp;quot;&lt;/span&gt;] ?? &lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            &lt;span class="kwrd"&gt;bool&lt;/span&gt; refresh = context.Request.Params[&lt;span class="str"&gt;&amp;quot;refresh&amp;quot;&lt;/span&gt;] == &lt;span class="str"&gt;&amp;quot;true&amp;quot;&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            &lt;span class="kwrd"&gt;int&lt;/span&gt; width, height;
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;int&lt;/span&gt;.TryParse(context.Request.QueryString[&lt;span class="str"&gt;&amp;quot;width&amp;quot;&lt;/span&gt;], &lt;span class="kwrd"&gt;out&lt;/span&gt; width))
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                width = 300;
&lt;/pre&gt;
&lt;pre&gt;
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;int&lt;/span&gt;.TryParse(context.Request.QueryString[&lt;span class="str"&gt;&amp;quot;height&amp;quot;&lt;/span&gt;], &lt;span class="kwrd"&gt;out&lt;/span&gt; height))
&lt;/pre&gt;
&lt;pre class="alt"&gt;
                height = 60;
&lt;/pre&gt;
&lt;pre&gt;
&amp;nbsp;
&lt;/pre&gt;
&lt;pre class="alt"&gt;
            &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] image = &lt;span class="kwrd"&gt;null&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre&gt;
            ThumbnailCacheManager 