<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6437009486382609650</id><updated>2012-01-30T11:18:51.780-06:00</updated><title type='text'>Steve Wortham's Blog</title><subtitle type='html'>A computer programmer's thoughts</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://swortham.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://swortham.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Steve Wortham</name><uri>http://www.blogger.com/profile/06878642454235403792</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://1.bp.blogspot.com/_uAFGogqHOtg/S6QHMLtiSMI/AAAAAAAAANw/8P82o2LWIkQ/s1600-R/SteveWortham.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>22</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6437009486382609650.post-4765183509931883467</id><published>2011-10-03T14:04:00.000-05:00</published><updated>2011-10-08T13:28:47.370-05:00</updated><title type='text'>How much faster is multiplication than division?</title><content type='html'>&lt;p&gt;This is one of those things I learned a long time ago when I used to write a lot of animations, games, etc -- multiplication is faster than division.  &lt;a href="http://www.intel.com/Assets/PDF/manual/248966.pdf"&gt;Intel has a reference manual&lt;/a&gt; that delves into this much deeper.  But I can't remember ever testing this to see exactly how much of a performance gap there was.  I figured division might be 2 or 3 times slower.  In fact, the difference is much greater than that.&lt;/p&gt;&lt;p&gt;I performed a little benchmark in C# on my AMD 3.0GHz quad core processor to see what's what.  As always, I performed my test with a release build of a console application and I ran it without debugging.&lt;/p&gt;Here's my code:&lt;pre class="prettyprint"&gt;&lt;code&gt;&lt;br /&gt;static void Main(string[] args)&lt;br /&gt;{&lt;br /&gt;	Stopwatch sw = new Stopwatch();&lt;br /&gt;&lt;br /&gt;	int iterations = 20000000;&lt;br /&gt;	double num;&lt;br /&gt;&lt;br /&gt;	sw.Start();&lt;br /&gt;	for (int i = 0; i &amp;lt; iterations; i++)&lt;br /&gt;	{&lt;br /&gt;		num = 1024;&lt;br /&gt;		num /= 2;&lt;br /&gt;		num /= 2;&lt;br /&gt;		num /= 2;&lt;br /&gt;		num /= 2;&lt;br /&gt;		num /= 2;&lt;br /&gt;	}&lt;br /&gt;	sw.Stop();&lt;br /&gt;	Console.WriteLine("Division: " + sw.ElapsedMilliseconds + " ms");&lt;br /&gt;&lt;br /&gt;	sw.Reset();&lt;br /&gt;	sw.Start();&lt;br /&gt;	for (int i = 0; i &amp;lt; iterations; i++)&lt;br /&gt;	{&lt;br /&gt;		num = 1024;&lt;br /&gt;		num *= 0.5;&lt;br /&gt;		num *= 0.5;&lt;br /&gt;		num *= 0.5;&lt;br /&gt;		num *= 0.5;&lt;br /&gt;		num *= 0.5;&lt;br /&gt;	}&lt;br /&gt;	sw.Stop();&lt;br /&gt;	Console.WriteLine("Multiplication: " + sw.ElapsedMilliseconds + " ms");&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;And here are the results:&lt;img border="0" src="http://4.bp.blogspot.com/-tcfcSjJp0aY/TooPtwiU1DI/AAAAAAAAAWc/NMGeUoXmP6o/s1600/mul-vs-div.PNG" /&gt;&lt;br /&gt;&lt;br /&gt;So multiplication is &lt;b&gt;41x faster&lt;/b&gt; in this case.  This is going to vary depending on the processor, of course.  But it's somewhat surprising that the compiler doesn't optimize for this.  I mean, dividing by 2 and multiplying by 0.5 is exactly the same thing, isn't it?  Couldn't the compiler automatically convert "num /= 2" to the much faster "num *= 0.5"?  In any case, it obviously doesn't do this and we as programmers should use multiplication instead of division whenever possible.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;UPDATE (October 8th, 2011)&lt;/b&gt;So this is crazy. I just changed the platform target from "Any CPU" to x86 and division is now much faster.  In fact, it's about the same speed as multiplication.  Incidentally having the "Optimize code" option checked actually slows down multiplication in this case.  Definitely some weird stuff going on.  But it would appear that there's something about running as a 64-bit app which is negatively impacting performance on my 64-bit quad core AMD CPU.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6437009486382609650-4765183509931883467?l=swortham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swortham.blogspot.com/feeds/4765183509931883467/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6437009486382609650&amp;postID=4765183509931883467' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/4765183509931883467'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/4765183509931883467'/><link rel='alternate' type='text/html' href='http://swortham.blogspot.com/2011/10/how-much-faster-is-multiplication-than.html' title='How much faster is multiplication than division?'/><author><name>Steve Wortham</name><uri>http://www.blogger.com/profile/06878642454235403792</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://1.bp.blogspot.com/_uAFGogqHOtg/S6QHMLtiSMI/AAAAAAAAANw/8P82o2LWIkQ/s1600-R/SteveWortham.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-tcfcSjJp0aY/TooPtwiU1DI/AAAAAAAAAWc/NMGeUoXmP6o/s72-c/mul-vs-div.PNG' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6437009486382609650.post-3350448291166006970</id><published>2011-07-14T18:46:00.003-05:00</published><updated>2011-07-14T18:54:32.949-05:00</updated><title type='text'>An Unconventional Thanksgiving Dinner</title><content type='html'>And now for something completely different.  I don't know how or why I thought of this in July.  Perhaps it's all the cooking shows I've been watching, or my ridiculous appetite as of late.  The idea just popped into my head.  &lt;br /&gt;&lt;br /&gt;Here's my question...&lt;br /&gt;&lt;b style="font-size: 18px"&gt;&lt;br /&gt;What would make a good non-traditional Thanksgiving dinner while still being distinctly American?&lt;/b&gt;&lt;br /&gt;No turkey, no stuffing, no cranberry sauce.  Perhaps most importantly, it would have to be even more delicious than the standard Thanksgiving fare.&lt;br /&gt;&lt;br /&gt;I've come up with four must-haves...&lt;br /&gt;&lt;br /&gt;&lt;h2 style="font-size: 18px"&gt;Chicken and Dumplings&lt;/h2&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://simplyrecipes.com/photos/chicken-dumplings-a.jpg" imageanchor="1" style=""&gt;&lt;img border="0" height="307" width="460" src="http://simplyrecipes.com/photos/chicken-dumplings-a.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;I love this stuff and it can be a meal in itself.  The chicken always comes out tender, the dumplings are great, and the vegetables complement it all.&lt;br /&gt;&lt;br /&gt;&lt;h2 style="font-size: 18px"&gt;Bratwurst&lt;/h2&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://media.onsugar.com/files/ons1/192/1922195/38_2009/168fc4333a0cf839_bratwurst-defn.xlarge.jpg" imageanchor="1" style=""&gt;&lt;img border="0" height="240" width="320" src="http://media.onsugar.com/files/ons1/192/1922195/38_2009/168fc4333a0cf839_bratwurst-defn.xlarge.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;While originally a German creation, bratwurst has pretty well established itself in American backyard barbeques.&lt;br /&gt;&lt;br /&gt;&lt;h2 style="font-size: 18px"&gt;Mustard Potato Salad&lt;/h2&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://content5.videojug.com/87/87ed3ffe-8eb9-f67e-3879-ff0008cd011e/how-to-make-mustard-potato-salad.WidePlayer.jpg" imageanchor="1" style=""&gt;&lt;img border="0" height="360" width="640" src="http://content5.videojug.com/87/87ed3ffe-8eb9-f67e-3879-ff0008cd011e/how-to-make-mustard-potato-salad.WidePlayer.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;The mustard in the potato salad adds a great flavor that should go well with the bratwurst.&lt;br /&gt;&lt;br /&gt;&lt;h2 style="font-size: 18px"&gt;Mixed Green Salad&lt;/h2&gt;Lettuce, fresh spinach, tomatoes, green olives, black olives, and feta cheese.  Topped with your choice of dressing.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;So that's my idea.  I'm still not sure what should be for dessert.  Pumpkin pie, perhaps?  That's a little too traditional, but it's good.  I'd be interested to hear your ideas.  Do you prepare a traditional Thanksgiving meal every year, or something a little different?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6437009486382609650-3350448291166006970?l=swortham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swortham.blogspot.com/feeds/3350448291166006970/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6437009486382609650&amp;postID=3350448291166006970' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/3350448291166006970'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/3350448291166006970'/><link rel='alternate' type='text/html' href='http://swortham.blogspot.com/2011/07/unconventional-thanksgiving-dinner.html' title='An Unconventional Thanksgiving Dinner'/><author><name>Steve Wortham</name><uri>http://www.blogger.com/profile/06878642454235403792</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://1.bp.blogspot.com/_uAFGogqHOtg/S6QHMLtiSMI/AAAAAAAAANw/8P82o2LWIkQ/s1600-R/SteveWortham.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6437009486382609650.post-2876455676346876391</id><published>2011-01-14T23:39:00.003-06:00</published><updated>2011-01-15T13:42:07.181-06:00</updated><title type='text'>My USB Microphone Woes</title><content type='html'>I got a USB VOIP phone to use on my PC for Skype.  And when I tried it out the sound quality was awful.  In my tests the recording coming from the microphone was almost robotic sounding.&lt;br /&gt;&lt;br /&gt;It was way too bad to put up with, so I ordered a USB headset.  In hindset, a headset is really more practical anyway for my needs.  So I got the headset, plugged it in, and Windows 7 immediately installed the appropriate drivers.  I set it up on Skype and... same problem.  It sounded awful.&lt;br /&gt;&lt;br /&gt;So I knew something weird was going on.  Then I had the bright idea of plugging the USB cable into the back of my computer (directly into the USB coming off the motherboard).  Voila, that solved it.  You see, I had been plugging in both devices into my internal multi-purpose card reader on the front of my computer.  The card reader is powered by USB 2.0, and acts as a sort of hub.  In the end I suppose the throughput was so low that it was massively compromising sound quality.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6437009486382609650-2876455676346876391?l=swortham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swortham.blogspot.com/feeds/2876455676346876391/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6437009486382609650&amp;postID=2876455676346876391' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/2876455676346876391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/2876455676346876391'/><link rel='alternate' type='text/html' href='http://swortham.blogspot.com/2011/01/my-usb-microphone-woes.html' title='My USB Microphone Woes'/><author><name>Steve Wortham</name><uri>http://www.blogger.com/profile/06878642454235403792</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://1.bp.blogspot.com/_uAFGogqHOtg/S6QHMLtiSMI/AAAAAAAAANw/8P82o2LWIkQ/s1600-R/SteveWortham.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6437009486382609650.post-5706345562736566252</id><published>2010-11-21T12:49:00.001-06:00</published><updated>2010-11-21T12:50:22.571-06:00</updated><title type='text'>Windows Phone 7 : It'll Be Fine</title><content type='html'>There have been dozens of similar articles pointing out the &lt;a href="http://www.thestreet.com/story/10916575/1/microsoft-sells-40k-windows-7-phones.html"&gt;underwhelming early sales&lt;/a&gt; of the new Windows Phone from Microsoft in the states.  By contrast, in other countries it's &lt;a href="http://www.eweekeurope.co.uk/news/uk-sales-of-windows-phone-7-hindered-by-shortages-11107"&gt;doing quite well&lt;/a&gt; and sales would have been even better if it hadn't been for some shortages.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;My Prediction&lt;/strong&gt;&lt;br /&gt;The iPhone has had such a large head start, but is only available on the most saturated mobile network in the U.S. -- AT&amp;T.  The Android phones offer alternatives available on multiple networks.  And like the Android, the new Windows Phones offer multiple phones from multiple manufacturers, but is currently limited to only AT&amp;T and T-Mobile.  Once it becomes available on Verizon next Spring I'm sure we'll see a surge in sales and a reason for app developers to continue to build apps for these phones.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6437009486382609650-5706345562736566252?l=swortham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swortham.blogspot.com/feeds/5706345562736566252/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6437009486382609650&amp;postID=5706345562736566252' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/5706345562736566252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/5706345562736566252'/><link rel='alternate' type='text/html' href='http://swortham.blogspot.com/2010/11/windows-phone-7-itll-be-fine.html' title='Windows Phone 7 : It&apos;ll Be Fine'/><author><name>Steve Wortham</name><uri>http://www.blogger.com/profile/06878642454235403792</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://1.bp.blogspot.com/_uAFGogqHOtg/S6QHMLtiSMI/AAAAAAAAANw/8P82o2LWIkQ/s1600-R/SteveWortham.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6437009486382609650.post-2699617695672391680</id><published>2010-11-18T09:17:00.003-06:00</published><updated>2010-11-18T10:28:26.575-06:00</updated><title type='text'>Windows Phone 7: Use of Back Button</title><content type='html'>I recently submitted a WP7 app to the marketplace and was denied because I failed to follow one of the guidelines.  You see, in order to submit an app successfully, you must meet these &lt;a href="http://go.microsoft.com/?linkid=9730556"&gt;certification requirements&lt;/a&gt;.  The one mistake I made is that I had a dialog box of sorts which didn't behave as it is supposed to when the back button is pressed.  The back button guidelines are here...  &lt;blockquote&gt;To maintain a consistent user experience, the Back button must only be used for backwards navigation in the application.&lt;br /&gt;a. Pressing the Back button from the first screen of an application must exit the application.&lt;br /&gt;b. Pressing the Back button must return the application to the previous page.&lt;br /&gt;&lt;b&gt;c. If the current page displays a context menu or a dialog, the pressing of the Back button must close the menu or dialog and cancel the backward navigation to the previous page.&lt;/b&gt;&lt;br /&gt;d. For games, when the Back button is pressed during gameplay, the game can choose to present a pause context menu or dialog or navigate the user to the prior menu screen. Pressing the Back button again while in a paused context menu or dialog closes the menu or dialog.&lt;/blockquote&gt;&lt;p&gt;As mentioned in point &lt;b&gt;"c"&lt;/b&gt; above, I needed to find a way to close the dialog box when the  back button is pressed.  The way to go about this was not immediately obvious to me.  I thought that I needed to do something fancy like navigate to a URI fragment on the page to open the dialog box.  That way you're actually adding something to the navigation history.  But I had a lot of problems trying to get this to work.&lt;/p&gt;&lt;p&gt;As it turns out, this is much simpler than I originally thought.  Let's say your dialog box is in a Popup control.  Well all you really have to do to intercept the back button and close the Popup is this...&lt;/p&gt;&lt;textarea readonly style="width: 80%; height: 250px;"&gt;// Constructorpublic MainPage(){ InitializeComponent(); this.BackKeyPress += MainPage_BackKeyPress;}private void MainPage_BackKeyPress(object sender, CancelEventArgs e){ if (popPassword.IsOpen) {  popPassword.IsOpen = false; // Close Dialog Box  e.Cancel = true; // Cancel Navigation }}&lt;/textarea&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6437009486382609650-2699617695672391680?l=swortham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swortham.blogspot.com/feeds/2699617695672391680/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6437009486382609650&amp;postID=2699617695672391680' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/2699617695672391680'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/2699617695672391680'/><link rel='alternate' type='text/html' href='http://swortham.blogspot.com/2010/11/windows-phone-7-use-of-back-button.html' title='Windows Phone 7: Use of Back Button'/><author><name>Steve Wortham</name><uri>http://www.blogger.com/profile/06878642454235403792</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://1.bp.blogspot.com/_uAFGogqHOtg/S6QHMLtiSMI/AAAAAAAAANw/8P82o2LWIkQ/s1600-R/SteveWortham.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6437009486382609650.post-1135201041680919399</id><published>2010-10-10T12:59:00.004-05:00</published><updated>2010-10-11T14:03:51.625-05:00</updated><title type='text'>Lakewood vs Golden vs Colorado Springs</title><content type='html'>&lt;h2&gt;Colorado Springs&lt;/h2&gt;I flew into Colorado Springs October 4th to check out apartments.  Having done plenty of research in advance, I had narrowed my search in the Springs down to just two apartment complexes in the southwest corner of the city.  After checking out both of them I was free to explore the city for a couple days.&lt;br /&gt;&lt;br /&gt;I had a nice view of Cheyenne Mountain (and Carls Jr) from my hotel...&lt;br /&gt;&lt;img src="http://swortham.smugmug.com/Vacation/Colorado-Vacation-2010/026/1035216387_Gur9B-M.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;In just a few minutes I was in the mountains...&lt;br /&gt;&lt;img src="http://swortham.smugmug.com/Vacation/Colorado-Vacation-2010/030/1035256207_wyTZ4-M.jpg" /&gt;&lt;br /&gt;&lt;img src="http://swortham.smugmug.com/Vacation/Colorado-Vacation-2010/IMG1262/1040510743_EUVoH-M.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;Even when driving aimlessly I stumbled across parks with beautiful scenery...&lt;br /&gt;&lt;img src="http://swortham.smugmug.com/Vacation/Colorado-Vacation-2010/IMG1263/1040512380_2a8gC-M.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;And I decided to take a hike...&lt;br /&gt;&lt;img src="http://swortham.smugmug.com/Vacation/Colorado-Vacation-2010/IMG1281/1040517251_nT6D8-M.jpg" /&gt;&lt;br /&gt;&lt;img src="http://swortham.smugmug.com/Vacation/Colorado-Vacation-2010/IMG1283/1040518346_vHbBS-M.jpg" /&gt;&lt;br /&gt;&lt;img src="http://swortham.smugmug.com/Vacation/Colorado-Vacation-2010/IMG1295/1040524606_Szr4p-L.jpg" /&gt;&lt;br /&gt;&lt;img src="http://swortham.smugmug.com/Vacation/Colorado-Vacation-2010/IMG1306/1040532111_yVrQx-M.jpg" /&gt;&lt;br /&gt;&lt;img src="http://swortham.smugmug.com/Vacation/Colorado-Vacation-2010/IMG1308/1040533429_JZhNN-M.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;It's beautiful here...&lt;br /&gt;&lt;img src="http://swortham.smugmug.com/Vacation/Colorado-Vacation-2010/IMG1311/1040534701_uhWTX-M.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Lakewood&lt;/h2&gt;First off, let me say that my whole reason to live in Colorado is to get away from the big city and be near the mountains.  Even though I wasn't technically that far from the mountains in Lakewood, I couldn't see them from most parts of the city.  Except for the weather, Lakewood felt a lot like a suburb of Dallas.  It's very flat and has lots of traffic.  So it really didn't appeal to me.  And for that reason I didn't take any pictures in the area.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Golden&lt;/h2&gt;When I arrived in Golden I was surrounded by 270 degrees of mountain views.  It's a spectacular place.&lt;br /&gt;&lt;br /&gt;This is the typical view of pretty much anything within 5 miles of downtown Golden...&lt;br /&gt;&lt;img src="http://swortham.smugmug.com/Vacation/Colorado-Vacation-2010/IMG1323/1040542362_bKkJp-M.jpg" /&gt;&lt;br /&gt;&lt;img src="http://swortham.smugmug.com/Vacation/Colorado-Vacation-2010/IMG1324/1040543193_u9ReY-M.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;I went straight for the mountains once again...&lt;br /&gt;&lt;img src="http://swortham.smugmug.com/Vacation/Colorado-Vacation-2010/IMG1330/1040548692_Tfc6u-M.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;Did a little hiking...&lt;br /&gt;&lt;img src="http://swortham.smugmug.com/Vacation/Colorado-Vacation-2010/IMG1368/1040566293_soJs7-M.jpg" /&gt;&lt;br /&gt;&lt;img src="http://swortham.smugmug.com/Vacation/Colorado-Vacation-2010/IMG1380/1040577226_5Gdek-M.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;And a little more...&lt;br /&gt;&lt;img src="http://swortham.smugmug.com/Vacation/Colorado-Vacation-2010/IMG1382/1040578083_2pyYM-M.jpg" /&gt;&lt;br /&gt;&lt;img src="http://swortham.smugmug.com/Vacation/Colorado-Vacation-2010/IMG1388/1040581357_VdKYs-M.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;Then I got out of there because it felt like it was about to rain.  But before I left I snapped this picture...&lt;br /&gt;&lt;img src="http://swortham.smugmug.com/Vacation/Colorado-Vacation-2010/IMG1401p/1043362532_hfabc-L.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;My Decision&lt;/h2&gt;In the end Colorado Springs was my favorite.  Even though I liked Golden too, Colorado Springs is big enough to have every modern convenience.  And southwest Colorado Springs is a particularly nice part of the city.  Everyone I met there is very nice, traffic isn't too bad, and I somehow just felt more comfortable there than anywhere else.  I will be moving in a few months.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://swortham.smugmug.com/Vacation/Colorado-Vacation-2010/"&gt;More pictures here...&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6437009486382609650-1135201041680919399?l=swortham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swortham.blogspot.com/feeds/1135201041680919399/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6437009486382609650&amp;postID=1135201041680919399' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/1135201041680919399'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/1135201041680919399'/><link rel='alternate' type='text/html' href='http://swortham.blogspot.com/2010/10/lakewood-vs-golden-vs-colorado-springs.html' title='Lakewood vs Golden vs Colorado Springs'/><author><name>Steve Wortham</name><uri>http://www.blogger.com/profile/06878642454235403792</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://1.bp.blogspot.com/_uAFGogqHOtg/S6QHMLtiSMI/AAAAAAAAANw/8P82o2LWIkQ/s1600-R/SteveWortham.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6437009486382609650.post-4267196945441085895</id><published>2010-08-24T14:23:00.003-05:00</published><updated>2010-08-24T14:28:11.390-05:00</updated><title type='text'>Soft Star Shoes RunAmocs: Two Weeks Later</title><content type='html'>After that &lt;a href="http://swortham.blogspot.com/2010/08/soft-star-shoes-runamocs-day-1.html"&gt;first day of running in my Runamocs&lt;/a&gt;, my feet were sore.  I'm not a barefoot or minimalist shoe runner by nature.  This is a new experience for me so my feet hurt for about 4 days after that first run.  &lt;br /&gt;&lt;br /&gt;I've been working out in different ways in the meantime, but I finally ran again last night.  This time I was a little more comfortable.  I pushed myself just as hard this time.  But today I have no foot pain to speak of, just a little healthy soreness in my calves.  It feels good.  I'll have to run again soon, perhaps a little faster next time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6437009486382609650-4267196945441085895?l=swortham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swortham.blogspot.com/feeds/4267196945441085895/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6437009486382609650&amp;postID=4267196945441085895' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/4267196945441085895'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/4267196945441085895'/><link rel='alternate' type='text/html' href='http://swortham.blogspot.com/2010/08/soft-star-shoes-runamocs-2-weeks-later.html' title='Soft Star Shoes RunAmocs: Two Weeks Later'/><author><name>Steve Wortham</name><uri>http://www.blogger.com/profile/06878642454235403792</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://1.bp.blogspot.com/_uAFGogqHOtg/S6QHMLtiSMI/AAAAAAAAANw/8P82o2LWIkQ/s1600-R/SteveWortham.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6437009486382609650.post-7645886215972567096</id><published>2010-08-11T22:48:00.004-05:00</published><updated>2010-08-24T14:24:52.309-05:00</updated><title type='text'>Soft Star Shoes RunAmocs: Day 1</title><content type='html'>I got my &lt;a href="http://www.softstarshoes.com/index.cfm?fuseaction=product.display&amp;Product_ID=1342"&gt;RunAmocs&lt;/a&gt; today...&lt;br /&gt;&lt;br /&gt;&lt;img src="http://swortham.smugmug.com/Other/Miscellaneous/Soft-Star-Shoes-RunAmoc/966983510_eG3TC-S.jpg" alt="Soft Star Shoes RunAmoc" /&gt;&lt;br /&gt;That's my foot in a size 13 RunAmoc running moccasin.  That's right, they're a lightweight moccasin designed to simulate barefoot running without being barefoot.  I know, it sounds kind of weird.  &lt;br /&gt;&lt;br /&gt;Allow me to explain.  I've been running short distances and doing sprints a couple times a week for the past several months.  The trouble I've been having is with building up my lower leg muscles enough so that I can run on the balls of my feet.  After years of running off &amp; on in modern running shoes, I had developed a heel strike style that was hard to break.  My poor form was slowing me down, and whenever I tried to correct it I suffered from a disconcerting ankle instability.  It felt as if I was on the verge of spraining my ankle as I was running full speed.&lt;br /&gt;&lt;br /&gt;And as usual, this little journey that led me to these shoes started off with some research on Google.  In my quest for a cure I came across surprising claims from those such as &lt;a href="http://www.barefootted.com/"&gt;Barefoot Ted&lt;/a&gt; that running barefoot was a completely viable option.  When you run barefoot, your body naturally compensates for its lack of protection by landing on the balls of your feet.  When your feet land this way, also called a forefoot strike, your knee will be slightly bent and your foot and calf muscle will actually absorb the shock of your landing far more than you might expect.  &lt;br /&gt;&lt;br /&gt;The revelation behind all of this is that your body's tendency to protect itself like this is actually considered good form.  Of course, running completely barefoot is rather extreme.  And it wasn't a step I felt ready to take just yet.&lt;br /&gt;&lt;br /&gt;So today I ran in my RunAmocs for the first time.  It was more of a leisurely jog to be honest. The 2mm rubber sole and leather insole underneath my feet was enough to protect my feet from rocks and anything sharp.  And, just as running barefoot would do, I felt naturally compelled to forefoot strike with every step.  My ankle instability I mentioned was still there, but I expect this to get better with time.  The muscles this hits in my feet and lower leg are muscles that I know have been neglected over the years, so I look forward to the soreness tomorrow.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://swortham.blogspot.com/2010/08/soft-star-shoes-runamocs-2-weeks-later.html"&gt;See my thoughts 2 weeks later &amp;gt;&amp;gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6437009486382609650-7645886215972567096?l=swortham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swortham.blogspot.com/feeds/7645886215972567096/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6437009486382609650&amp;postID=7645886215972567096' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/7645886215972567096'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/7645886215972567096'/><link rel='alternate' type='text/html' href='http://swortham.blogspot.com/2010/08/soft-star-shoes-runamocs-day-1.html' title='Soft Star Shoes RunAmocs: Day 1'/><author><name>Steve Wortham</name><uri>http://www.blogger.com/profile/06878642454235403792</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://1.bp.blogspot.com/_uAFGogqHOtg/S6QHMLtiSMI/AAAAAAAAANw/8P82o2LWIkQ/s1600-R/SteveWortham.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6437009486382609650.post-3136119365449599443</id><published>2010-06-18T15:44:00.004-05:00</published><updated>2010-06-18T16:37:21.683-05:00</updated><title type='text'>Lingering Event Handlers in ASP.NET Web Forms</title><content type='html'>I hate dealing with dynamically added user controls.  Whenever you add multiple user controls to your page through the Controls.Add mechanism, the order of events becomes a great big mess to handle.  There are tons of articles around the web that try to explain how you can alleviate some of these issues.  But I'm convinced that unless you were on the team that built ASP.NET Web Forms, it's impossible to understand these issues completely.&lt;br /&gt;&lt;br /&gt;I'm here to talk about one issue in particular I came across last night and solved today.  It relates to custom events.  If your parent page has a button on it that you want to be intercepted by a child control, then it can be done something like this:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Parent Page&lt;/b&gt;&lt;br /&gt;&lt;pre style="color: #009"&gt;Private Sub btnSave_Click() Handles btnSave.Click&lt;br /&gt;  CurrentWebsiteApp.OnSavePage() ' Custom function that raises a custom SavePageEvent&lt;br /&gt;End Sub&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Dynamically added user control&lt;/b&gt;&lt;br /&gt;&lt;pre style="color: #009"&gt;Private Sub Page_Init() Handles Me.Init&lt;br /&gt;  RemoveHandler CurrentWebsiteApp.SavePageEvent, AddressOf SaveMe&lt;br /&gt;  AddHandler CurrentWebsiteApp.SavePageEvent, AddressOf SaveMe&lt;br /&gt;End Sub&lt;br /&gt;&lt;br /&gt;Private Sub SaveMe()&lt;br /&gt;  ' Save some stuff&lt;br /&gt;End Sub&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And this works.  However, what I discovered is that even after this user control is disposed the event handler persists for the user's session.  And if you have this same set up on dozens of dynamic user controls throughout your website then the SaveMe() function might be called on user controls that are no longer a part of the page.  Craziness, I know.&lt;br /&gt;&lt;br /&gt;The solution I found is to do this in your user control:&lt;br /&gt;&lt;br /&gt;&lt;pre style="color: #009"&gt;Public Overrides Sub Dispose()&lt;br /&gt;  RemoveHandler CurrentWebsiteApp.SavePageEvent, AddressOf SaveMe&lt;br /&gt;  MyBase.Dispose()&lt;br /&gt;End Sub&lt;/pre&gt;&lt;br /&gt;This will reliably remove the handler for this control when the control is disposed.  This effectively prevents the handler from lingering on.  Problem solved!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6437009486382609650-3136119365449599443?l=swortham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swortham.blogspot.com/feeds/3136119365449599443/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6437009486382609650&amp;postID=3136119365449599443' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/3136119365449599443'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/3136119365449599443'/><link rel='alternate' type='text/html' href='http://swortham.blogspot.com/2010/06/lingering-event-handlers-in-aspnet-web.html' title='Lingering Event Handlers in ASP.NET Web Forms'/><author><name>Steve Wortham</name><uri>http://www.blogger.com/profile/06878642454235403792</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://1.bp.blogspot.com/_uAFGogqHOtg/S6QHMLtiSMI/AAAAAAAAANw/8P82o2LWIkQ/s1600-R/SteveWortham.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6437009486382609650.post-9149092152680292230</id><published>2010-05-03T17:35:00.011-05:00</published><updated>2010-05-03T18:19:55.318-05:00</updated><title type='text'>My Review of Peter's Data Entry Suite</title><content type='html'>&lt;h4&gt;The Task at Hand&lt;/h4&gt;&lt;p&gt;A couple years ago I began one of the biggest projects of my career.  I work for TechInsurance and over the last couple years we've been rebuilding the database, agency management system, and websites (&lt;a href="http://www.techinsurance.com/"&gt;www.techinsurance.com&lt;/a&gt; and &lt;a href="http://www.businessinsurancenow.com/"&gt;www.businessinsurancenow.com&lt;/a&gt;).  It's a massive undertaking.  At this point it's &lt;i&gt;almost&lt;/i&gt; done (we're so close).&lt;/p&gt;&lt;p&gt;My job is on the website end of things.  Each website has its own dynamic insurance application with their own sets of questions.  I say sets, because that's really what they are.  The questions themselves are highly dynamic in nature so that it's rare that any one person will be asked the exact same set of questions as another.  An engineer is going to be asked different questions than a custom programmer.  Moreover, the questions also vary depending on the selections you make on an individual page.  For example, answering "Yes" to one question may cause another required question to appear on a page.  This is great for the user because they don't have to answer more questions than are necessary, but it's complicated for me.&lt;/p&gt;&lt;p&gt;So one of the daunting tasks for me was to scrap all of the existing questions and rewrite them.  The previous incarnation of the site was written in ASP.NET 1.1, where the client side validation doesn't work in browsers other than IE.  So that's just one thing we were looking to improve.  The constant struggle I've always had was that I had to write lengthy Javascript to handle the expanding/collapsing controls while simultaneously turning on or off the validators accordingly.  And all of this logic had to be written in my code-behind .NET code as well.  This meant that to be thorough I absolutely had to test the forms in both IE and Firefox to ensure that only the visible questions were required in both the client side and server side validation.  I mean, if a hidden control's validator is ever set to the "Enabled" state then that spells trouble.  How can you fill out a field that's invisible?  It's not easy.  And this is a problem I'd run into more often than I'd like when dealing with applications of this level of complexity.&lt;/p&gt;&lt;h4&gt;Enter Peter Blum&lt;/h4&gt;&lt;p&gt;I thought that surely someone had a solution to simplify this process.  And eventually I stumbled across a solution at &lt;a href="http://www.peterblum.com/"&gt;www.peterblum.com&lt;/a&gt;.  I had known about Peter's awesome validators for awhile.  They're much more powerful than even the latest version of ASP.NET 4 validators.  They allow custom formatting rules in the form of HTMLBefore and HTMLAfter around the error message you specify.  You can specify extra controls to fire the validators other than the control it's validating.  You can wire a validator to a label or other form element for better error visualization effects.  I could go on and on.&lt;/p&gt;&lt;p&gt;But in addition to these validators he offers something in the suite that solves my problem, and solves it well.  It's the MultiFieldStateController.  The MultiFieldStateController offers a declarative way of handling the complex visibility conditions I had to deal with.&lt;/p&gt;&lt;h4&gt;Peter Blum Controls in the Real World&lt;/h4&gt;&lt;p&gt;Let's take the classic mailing address example.  Often times the user doesn't need to enter their mailing address because it's the same as their physical address.&lt;/p&gt;&lt;p&gt;So if we have a question like this:&lt;/p&gt;&lt;textarea rows="6" style="width: 90%; overflow: auto;"&gt;Is your mailing address the same as your physical address?&lt;asp:RadioButtonList ID="rdoSameAddress" runat="server" RepeatDirection="Horizontal"&gt;	&lt;asp:ListItem Value="True"&gt;Yes&lt;/asp:ListItem&gt;	&lt;asp:ListItem Value="False"&gt;No&lt;/asp:ListItem&gt;&lt;/asp:RadioButtonList&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;p&gt;Then we can handle the visibility condition like this:&lt;/p&gt;&lt;textarea rows="15" style="width: 90%; overflow: auto;"&gt;&lt;des:MultiFieldStateController ID="mfsc1" runat="server" ConditionTrue-Visible="true" ConditionFalse-Visible="false"&gt;	&lt;ControlConnections&gt;		&lt;des:FSAControlConnection ControlID="trMailingAddress" /&gt; 	&lt;/ControlConnections&gt;	&lt;ConditionContainer&gt;		&lt;des:MultiCondition Operator="AND"&gt;			&lt;Conditions&gt;				&lt;des:RequiredListCondition ControlIDToEvaluate="rdoSameAddress" /&gt;				&lt;des:CompareToValueCondition ControlIDToEvaluate="rdoSameAddress" ValueToCompare="False" /&gt;			&lt;/Conditions&gt;		&lt;/des:MultiCondition&gt;	&lt;/ConditionContainer&gt;&lt;/des:MultiFieldStateController&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;p&gt;And then the mailing address and validator below might look like this:&lt;/p&gt;&lt;textarea rows="20" style="width: 90%; overflow: auto;"&gt;&lt;table width="100%"&gt;	&lt;tr id="trMailingAddress" runat="server"&gt;		&lt;th&gt;			&lt;asp:Label ID="lblMailingAddress" runat="server" AssociatedControlID="txtMailingAddress"&gt;Address&lt;/asp:Label&gt;		&lt;/th&gt;		&lt;td&gt;			&lt;asp:TextBox id="txtMailingAddress" runat="server" width="275" MaxLength="100" /&gt;			&lt;des:RequiredTextValidator ID="RequiredTextValidator6" runat="server" ControlIDToEvaluate="txtMailingAddress" 			ErrorMessage="This information is required" Label-LabelControlID="lblMailingAddress"&gt;				&lt;ErrorFormatterContainer&gt;					&lt;des:TextErrorFormatter Display="Dynamic" HTMLBefore="&lt;br /&gt;" 					ImageURL="/images/quote/ErrorBullet.png"&gt;&lt;/des:TextErrorFormatter&gt;				&lt;/ErrorFormatterContainer&gt;				&lt;EnablerContainer&gt;					&lt;des:VisibleCondition ControlIDToEvaluate="trMailingAddress" IsVisible="true" /&gt;				&lt;/EnablerContainer&gt;			&lt;/des:RequiredTextValidator&gt;		&lt;/td&gt;	&lt;/tr&gt;	&lt;!-- City, state, and zip fields go here --&gt;&lt;/table&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;p&gt;And that's it.  The mailing address will only appear when the answer to the above question is "False".  And then whether RequiredTextValidator fires or not is dependent on the des:VisibleCondition.  The beauty part is that this completely takes care of both the Javascript and server-side end of things.  This is a relatively straightforward example, but you can also combine conditions and do some pretty powerful stuff.&lt;/p&gt;&lt;p&gt;With as much time and effort this has saved me, these features were easily enough to sell me on the product.  Of course this is just a small aspect of what Peter's suite is capable of.  And his support and documentation are legendary so I can recommend the suite without hesitation.  If you're looking to simplify your life and avoid ASP.NET Web Form headaches then I'd seriously consider checking it out.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6437009486382609650-9149092152680292230?l=swortham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swortham.blogspot.com/feeds/9149092152680292230/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6437009486382609650&amp;postID=9149092152680292230' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/9149092152680292230'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/9149092152680292230'/><link rel='alternate' type='text/html' href='http://swortham.blogspot.com/2010/05/my-review-of-peters-data-entry-suite.html' title='My Review of Peter&apos;s Data Entry Suite'/><author><name>Steve Wortham</name><uri>http://www.blogger.com/profile/06878642454235403792</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://1.bp.blogspot.com/_uAFGogqHOtg/S6QHMLtiSMI/AAAAAAAAANw/8P82o2LWIkQ/s1600-R/SteveWortham.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6437009486382609650.post-5037764513177494530</id><published>2010-03-22T14:19:00.002-05:00</published><updated>2010-03-22T16:42:57.536-05:00</updated><title type='text'>I'm Sorry, but a Tweet Cannot Contain My...</title><content type='html'>I'll be honest.  I'm 27 years old and I don't understand Twitter.&lt;br /&gt;&lt;br /&gt;I created one of my first websites back in 1999 where I chronicled my adventures in OpenGL programming.  I'd write little news blurbs rich with links and images to and from my work.  It was a way of putting my thoughts down in writing and sharing what I learn.  Around the same time blogs were just starting up, offering much of the same kind of rich content.  I completely understand and love blogs.  I have 3 of them.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://upload.wikimedia.org/wikipedia/commons/thumb/5/50/Bundesarchiv_Bild_183-2008-0516-500%2C_Fernschreibmaschine_mit_Telefonanschluss.jpg/220px-Bundesarchiv_Bild_183-2008-0516-500%2C_Fernschreibmaschine_mit_Telefonanschluss.jpg" style="float: right;" /&gt;Twitter, however, is a completely different animal.  Whenever I look at someone's Twitter messages I'm completely and hopelessly lost.  The imposed 140-character limit is so debilitating to the writer that it's devolving the quality of communication.  The short-hand style of writing that people are forced to use is often confusing and never pretty.  On top of that, the messages are littered with @ and # symbols, often with short-hand replies between members that I don't really care to read.   Why has our communication devolved into this?  I mean, this is almost like &lt;a href="http://en.wikipedia.org/wiki/Teleprinter"&gt;Teletype&lt;/a&gt;.  We've invented better things.&lt;br /&gt;&lt;br /&gt;Now, it may come as a surprise but I do have a Twitter account.  I've made about 4 tweets, I think.  I would have tweeted my distaste for Twitter... on Twitter, but I don't know if I could have confined it to 140 characters.  Let me give it a try anyway...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;@Twitter: 140 chars will be bane of my exstnce.Oh I how I wish I cld convey my ides more clerly.Mite as well use teletype or morse code, yo&lt;/blockquote&gt;&lt;br /&gt;I couldn't get that last period in there.  Meh... close enough.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6437009486382609650-5037764513177494530?l=swortham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swortham.blogspot.com/feeds/5037764513177494530/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6437009486382609650&amp;postID=5037764513177494530' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/5037764513177494530'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/5037764513177494530'/><link rel='alternate' type='text/html' href='http://swortham.blogspot.com/2010/03/im-sorry-but-tweet-cannot-contain-my.html' title='I&apos;m Sorry, but a Tweet Cannot Contain My...'/><author><name>Steve Wortham</name><uri>http://www.blogger.com/profile/06878642454235403792</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://1.bp.blogspot.com/_uAFGogqHOtg/S6QHMLtiSMI/AAAAAAAAANw/8P82o2LWIkQ/s1600-R/SteveWortham.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6437009486382609650.post-7389545155934457664</id><published>2010-03-10T14:03:00.005-06:00</published><updated>2010-03-10T14:55:35.252-06:00</updated><title type='text'>Latency, Requests, CSS Sprites, and You</title><content type='html'>Ah yes, more website optimization talk.  I love this stuff.&lt;br /&gt;&lt;br /&gt;Did you know that often times the slowest part of loading a web page for the first time can be attributed to the inherent latency and overhead from the requests themselves?  In fact, most modern web pages consist of much more than a single html file.  Most pages also have an external css file, sometimes a js file or two, and multiple images.  It's not uncommon to see over 20 files altogether necessary for just one web page.  Edmunds.com, for example, has over 40 files on their home page.&lt;br /&gt;&lt;br /&gt;The problem with this is that each and every file must be requested by your browser individually.  So what?  Well using &lt;a href="http://www.fiddler2.com/"&gt;Fiddler&lt;/a&gt; I've gathered the first request header that's sent when I go to www.google.com:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;GET http://www.google.com/ HTTP/1.1&lt;br /&gt;Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*&lt;br /&gt;Accept-Language: en-US&lt;br /&gt;User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; GTB0.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; OfficeLiveConnector.1.4; OfficeLivePatch.1.3)&lt;br /&gt;Accept-Encoding: gzip, deflate&lt;br /&gt;Connection: Keep-Alive&lt;br /&gt;Host: www.google.com&lt;br /&gt;Cookie: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&lt;br /&gt;&lt;/blockquote&gt;That amounts to 1,036 bytes of data.&lt;br /&gt;&lt;br /&gt;And here's the response header:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;HTTP/1.1 200 OK&lt;br /&gt;Date: Wed, 10 Mar 2010 19:45:31 GMT&lt;br /&gt;Expires: -1&lt;br /&gt;Cache-Control: private, max-age=0&lt;br /&gt;Content-Type: text/html; charset=UTF-8&lt;br /&gt;Content-Encoding: gzip&lt;br /&gt;Server: gws&lt;br /&gt;Content-Length: 4497&lt;br /&gt;X-XSS-Protection: 0&lt;/blockquote&gt;&lt;br /&gt;That's 220 bytes.&lt;br /&gt;&lt;br /&gt;From what I've observed in request/response payload alone you can expect an average of 800 bytes to 1,600 bytes of additional fluff for every file.  In our hypothetical page above with 20 files for a given page, that amounts to 16,000 to 32,000 bytes.  In addition to this extra fluff that's being sent back &amp; forth you also have to take into account network latency of the connection itself.  Each of these files require a connection of its own.  A connection is normally established in a matter of milliseconds.  But again, when dealing with multiple files it adds up.&lt;br /&gt;&lt;br /&gt;The part of this story which was a big eye opener for me is when you're dealing with tiny files.  I often use 1-pixel wide images for gradients and such which amount to a couple hundred bytes.  Say for example you create 4 of these tiny gradient images.  Well, that extra fluff from the request/response we talked about might easily be 5 times the size of the image itself.&lt;br /&gt;&lt;br /&gt;If you're like me then I've officially shaken the very foundation of everything you thought you knew about website optimization.  So what can you do about it?&lt;br /&gt;&lt;br /&gt;Well, I'd highly recommend downloading Yahoo's &lt;a href="http://developer.yahoo.com/yslow/"&gt;YSlow plug-in&lt;/a&gt;.  It's designed for Firebug in Firefox.  After you install it, bring up your website in Firefox and run YSlow and see what it says.  It offers excellent advice on a number of common issues that can affect performance, some of which are very easily solvable.&lt;br /&gt;&lt;br /&gt;As for advice on this topic specifically there are a couple things you can do:&lt;br /&gt;&lt;br /&gt;1.) &lt;b&gt;Create &lt;a href="http://websitetips.com/articles/css/sprites/"&gt;CSS Image Sprites&lt;/a&gt;&lt;/b&gt;.  The idea here is to combine images or icons into one bigger image, and then use clever CSS background positioning to show each image appropriately.  This can drastically reduce the file count.  And although it requires a lot of extra effort, it can be well worth it.&lt;br /&gt;&lt;br /&gt;2.) &lt;b&gt;Host your external css, js, and images on a &lt;a href="http://code.google.com/speed/page-speed/docs/request.html"&gt;cookieless domain&lt;/a&gt;&lt;/b&gt;.  If your site doesn't use any cookies to begin with then you won't need to worry about this.  But if it ever sets cookies then storing your images on a separate domain that's dedicated to static content can drastically reduce the payload of every request.  Just look at the Google request header above and you can see that half of its size comes from that cookie.&lt;br /&gt;&lt;br /&gt;This whole concept of request/response overhead may change your approach to a lot of things.  But it's important not to take this too far.  There's still a strong case to use external js and css files, for example.  Any time you have multiple pages that point to the same resources you have the advantage of caching on your side.  I talk a little about that in my other &lt;a href="http://swortham.blogspot.com/2007/10/three-ways-to-improve-your-websites.html"&gt;website optimization article&lt;/a&gt;.  But CSS sprites and cookieless domains mentioned above are both valuable techniques with very few downsides.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6437009486382609650-7389545155934457664?l=swortham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swortham.blogspot.com/feeds/7389545155934457664/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6437009486382609650&amp;postID=7389545155934457664' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/7389545155934457664'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/7389545155934457664'/><link rel='alternate' type='text/html' href='http://swortham.blogspot.com/2010/03/latency-requests-css-sprites-and-you.html' title='Latency, Requests, CSS Sprites, and You'/><author><name>Steve Wortham</name><uri>http://www.blogger.com/profile/06878642454235403792</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://1.bp.blogspot.com/_uAFGogqHOtg/S6QHMLtiSMI/AAAAAAAAANw/8P82o2LWIkQ/s1600-R/SteveWortham.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6437009486382609650.post-861831796472267790</id><published>2009-10-20T15:42:00.010-05:00</published><updated>2012-01-30T11:18:51.789-06:00</updated><title type='text'>When to use ASP.NET Web Forms and when to use ASP.NET MVC</title><content type='html'>&lt;span style="font-style: italic;"&gt;Disclaimer: I don't work for Microsoft and I have no reason to push one technology over another.  I just want to get my thoughts down in writing.  With that said...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I've been building websites with ASP.NET web forms for 8 years now.  Wow, has it really been that long?  I still remember trying out the first ASP.NET public beta.  As a performance enthusiast, the biggest thing that appealed to me was the way it was a compiled language unlike classic ASP.  And there was indeed a large leap in performance across the board.  But as I used it more I began to realize how much of a departure from ASP it really was.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The Magical ASP.NET Web Forms&lt;/span&gt;&lt;br /&gt;The whole idea behind ASP.NET web forms was to simplify things for the web developer by almost mimicking the way Windows applications work.  When an event is raised, an action is performed.  So was born the concept of postbacks and ViewStates to make the modern web application stateful, so to speak.  ViewState information is stored in your HTML page to track the state of an HTML form.  And postbacks intercept this ViewState data behind the scenes to handle a lot of functionality you'd otherwise have to write yourself.  This magical process allows a lot of the built-in web controls to do their thing. Perhaps the most profound of which are the built-in validator controls that automatically handle both client-side and server-side validation.&lt;br /&gt;&lt;br /&gt;So this sounds so good, why mess with this system?  Well, you may have noticed that I said that the ViewState data is stored in the HTML.  The ViewState can sometimes become quite large, adding a lot of bulk to your pages.  Not only can this slow down the experience for the user, but it potentially detracts from the SEO (search engine optimization) potential of your pages.  One of the goals of SEO should be to achieve the &lt;a href="http://www.collinsinternet.com/code-to-text-ratio/" rel="nofollow"&gt;best textual content to HTML ratio possible&lt;/a&gt;, so filling your HTML with a bunch of ViewState gibberish isn't going to help your cause.  &lt;br /&gt;&lt;br /&gt;Secondly, as useful as many of the web controls in ASP.NET web forms are, some of them have their faults.  For example, pretty much everything requires a postback.  Even the DataPager control used for paging in a DataGrid requires a postback.  This is &lt;a href="http://stackoverflow.com/questions/1228083/if-i-need-pagination-support-should-i-use-a-listview-or-a-repeater/1228198#1228198"&gt;not a good thing for SEO or for the user&lt;/a&gt;.  So the question remains, if some of these built-in controls have problems like this, then why bother with web forms?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Enter ASP.NET MVC&lt;/span&gt;&lt;br /&gt;In some ways ASP.NET MVC is a step backwards.  You don't have the dozens of web controls on your side to help you out.  At first glance some of the &lt;a href="http://www.asp.net/learn/mvc-videos/"&gt;MVC examples&lt;/a&gt; may even look like classic ASP to you.  But it has some structure to it: models, views, and controllers.  It's the whole idea of the separation of layers put into practice.  &lt;br /&gt;&lt;br /&gt;- &lt;span style="font-weight: bold;"&gt;Models&lt;/span&gt;&amp;nbsp;define your data.&lt;br /&gt;- &lt;span style="font-weight: bold;"&gt;Views&lt;/span&gt; are your pages.&lt;br /&gt;- &lt;span style="font-weight: bold;"&gt;Controllers&lt;/span&gt; are designed to tell your application what page to go to and when, and also hold much of your business logic.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;So the idea with all of this is to allow complete control of your rendered markup and application flow while encouraging some structure in your application.  MVC doesn't generate or rely on ViewState (yay!), and it promotes this idea of writing URL's with folder names only.  In other words, &lt;a href="http://swortham.blogspot.com/2008/12/redirecting-default-page-defaultaspx-to.html"&gt;gone are the days of default.aspx&lt;/a&gt;.  Once again, both of those little details are good for SEO.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;So what should I use?&lt;/span&gt;&lt;br /&gt;I recently rebuilt my site &lt;a href="http://regexhero.net/"&gt;Regex Hero&lt;/a&gt; with ASP.NET MVC.  I primarily did it because I wanted to rid my site of ViewState and get the best SEO possible.  And I also did it for the learning experience.  But I do still think there's a time for both.&lt;br /&gt;&lt;br /&gt;If you're building a complicated site with a lot of HTML forms and form interactivity then you may want to stick with ASP.NET web forms.  Some of its built-in controls can be a big time saver for the developer and can be worth their little quirks.&lt;br /&gt;&lt;br /&gt;But if you're building a public-facing site then the full control of your markup that MVC gives you is a big thing.  And if there's not a massive amount of forms to build then I'd strongly consider ASP.NET MVC for the full control of your HTML markup that you'll gain.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6437009486382609650-861831796472267790?l=swortham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swortham.blogspot.com/feeds/861831796472267790/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6437009486382609650&amp;postID=861831796472267790' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/861831796472267790'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/861831796472267790'/><link rel='alternate' type='text/html' href='http://swortham.blogspot.com/2009/10/when-to-use-aspnet-web-forms-and-when.html' title='When to use ASP.NET Web Forms and when to use ASP.NET MVC'/><author><name>Steve Wortham</name><uri>http://www.blogger.com/profile/06878642454235403792</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://1.bp.blogspot.com/_uAFGogqHOtg/S6QHMLtiSMI/AAAAAAAAANw/8P82o2LWIkQ/s1600-R/SteveWortham.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6437009486382609650.post-7642699791783036701</id><published>2009-03-23T15:01:00.003-05:00</published><updated>2009-03-23T15:14:52.560-05:00</updated><title type='text'>VB.NET 2008 - XML parser makes writing Javascript easy</title><content type='html'>Today I had the need to write some Javascript in an ASP.NET VB code-behind.  I was about to do it the old way with quotes and ampersands and underscores.  &lt;br /&gt;&lt;br /&gt;And then I had a thought.  VB in Visual Studio 2008 has a built-in XML parser.  So all I have to do is start typing xml and the IDE will recognize it.  So why not put the Javascript inside a CDATA tag in some XML and let VB take care of the rest?&lt;br /&gt;&lt;br /&gt;It works!  Here's an example...&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Dim script = &amp;lt;xml&amp;gt;&lt;br /&gt;  &amp;lt;![CDATA[&lt;br /&gt;    alert("Hello World!");&lt;br /&gt;  ]]&amp;gt;&lt;br /&gt;  &amp;lt;/xml&amp;gt;&lt;br /&gt;&lt;br /&gt;Response.Write(script.Value)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This makes it so easy to write Javascript in a code-behind, especially when you have a lot of Javascript to write.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6437009486382609650-7642699791783036701?l=swortham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swortham.blogspot.com/feeds/7642699791783036701/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6437009486382609650&amp;postID=7642699791783036701' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/7642699791783036701'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/7642699791783036701'/><link rel='alternate' type='text/html' href='http://swortham.blogspot.com/2009/03/vb-2008.html' title='VB.NET 2008 - XML parser makes writing Javascript easy'/><author><name>Steve Wortham</name><uri>http://www.blogger.com/profile/06878642454235403792</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://1.bp.blogspot.com/_uAFGogqHOtg/S6QHMLtiSMI/AAAAAAAAANw/8P82o2LWIkQ/s1600-R/SteveWortham.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6437009486382609650.post-5946836790007157735</id><published>2008-12-09T16:27:00.011-06:00</published><updated>2010-03-24T11:22:35.408-05:00</updated><title type='text'>Redirecting the Default Page (/default.aspx) to the Root (/)</title><content type='html'>&lt;strong&gt;The problem&lt;/strong&gt;&lt;br /&gt;Today I found that one of the sites I work on is being linked to from other sites in two different ways.  Some links had default.aspx at the end, and some didn't.  So what?  Well, sure technically they both bring up the same page.  But the search engines don't see it that way.  This means that the link popularity for the home page was being split between two URL's.  That's bad.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The search for a solution&lt;/strong&gt;&lt;br /&gt;So my search began for a solution.  I knew that if I simply put the redirection code on default.aspx that I'd create an infinite loop.  So I figured I'd put a statement in there to only redirect if "/default.aspx" is in the path.  Unfortunately, I quickly found that ASP.NET sees both the "/" and the "/default.aspx" URL's as being the same and impossible to distinguish the difference.  I heard some people say that it's possible to do this with an HTTPHandler in .NET, but without any examples I leaned more towards a solution on the IIS side of things.  Now for all I know IIS 7 might be able to do what I want natively, but being stuck with IIS 6 it looked as though my only option was to install an ISAPI filter to take care of all this.  So that's what I did.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The solution&lt;/strong&gt;&lt;br /&gt;I stumbled across Ionic's ISAPI Rewrite Filter (IIRF) which is completely free and powerful enough to do exactly what I needed.  The information and download link is all found here: &lt;br /&gt;&lt;a href="http://www.codeplex.com/IIRF"&gt;http://www.codeplex.com/IIRF&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Follow the instructions in the readme to install it on your IIS server and configure it for your website.  You can use one of their sample "IsapiRewrite4.ini" files as a test and then go from there.  But if you want to redirect default.aspx to the root of the site as I did, then read on.&lt;br /&gt;&lt;br /&gt;I'll show you my ini file in my production environment first, and then explain how it works.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;UPDATE.&lt;/b&gt;  A good friend of mine, Malik Emami from &lt;a href="https://www.billtrackeronline.com/" target="_blank"&gt;Bill Tracker Online&lt;/a&gt;, mentioned that my script doesn't work with postbacks.  He found a fix.  All you have to do is include a RewriteCond to only perform the redirect on a GET.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;# IsapiRewrite4.ini&lt;br /&gt;#&lt;br /&gt;# ini file for the ISAPI rewriter. &lt;br /&gt;# &lt;br /&gt;# Tue, 9 Dec 2008  01:49&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;RewriteFilterPriority HIGH&lt;br /&gt;RewriteLogLevel 0&lt;br /&gt;&lt;br /&gt;# Any incoming URL that starts with /default.aspx will be redirected&lt;br /&gt;# to the root directory while preserving any query strings.&lt;br /&gt;&lt;br /&gt;RewriteCond %{REQUEST_METHOD} GET [I]&lt;br /&gt;RedirectRule ^/default\.aspx(.*)  /$1 [I,R=301]&lt;/blockquote&gt;&lt;br /&gt;You can take the above and try it out for yourself and it may just work as is.  But as always, I suggest testing thoroughly in a development environment before throwing this out on your live site.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Breaking it down&lt;/strong&gt;&lt;br /&gt;&lt;blockquote&gt;RewriteFilterPriority HIGH&lt;/blockquote&gt;&lt;br /&gt;In production I want IIRF to run as fast as possible since I'm essentially waiting on it to process the rules for every request.  Albeit we're talking about imperceivable milliseconds but hey, I'm a speed freak.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;RewriteLogLevel 0&lt;/blockquote&gt;&lt;br /&gt;This is actually the default setting.  RewriteLogLevel 0 means there will be no logging at all done by IIRF.  Again, this setting is for pure speed.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;RedirectRule ^/default\.aspx(.*)  /$1 [I,R=301]&lt;/blockquote&gt;&lt;br /&gt;There are a few things going on in this single line of code so allow me to break it down further.  &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;RedirectRule&lt;/blockquote&gt;&lt;br /&gt;If you look through the IIRF examples you'll probably notice that they mostly use the RewriteRule command, while I'm using the RedirectRule command.  Redirection is what we need here because we want IIRF to return a status code indicating that the page has moved (more on that later).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;^/default\.aspx(.*)&lt;/blockquote&gt;&lt;br /&gt;This is the URL we're looking to redirect from.  It's a parameterized regular expression that matches any URL starting with "/default.aspx"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;/$1&lt;/blockquote&gt;&lt;br /&gt;This is the URL we're looking to redirect to (but only if the previous regular expression is satisfied).  The "$1" part grabs the parameter from the regular expression and puts it into this URL.  So in the event someone goes to "/default.aspx?animal=monkey" they will be redirected to "/?animal=monkey"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;[I,R=301]&lt;/blockquote&gt;&lt;br /&gt;These are both modifiers documented in the IIRF readme.  The "I" modifier specifies case-insensitive matching, which is what we want.  And the "R=301" modifier specifies to use a 301 redirection, which is perfect for the search engines.  The 301 status code specifies that a page has permanently moved.  And that means that any link popularity from the old URL will be carried onto the new URL.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In effect, I've allowed the link popularity between "/" and "/default.aspx" to join forces, increasing the chances of the home page to place well in Google search results.  At this point it's just a matter of time before Google re-indexes the site.  I anticipate the PageRank and the traffic for the home page will go up so I'll be keeping an eye on it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6437009486382609650-5946836790007157735?l=swortham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swortham.blogspot.com/feeds/5946836790007157735/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6437009486382609650&amp;postID=5946836790007157735' title='22 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/5946836790007157735'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/5946836790007157735'/><link rel='alternate' type='text/html' href='http://swortham.blogspot.com/2008/12/redirecting-default-page-defaultaspx-to.html' title='Redirecting the Default Page (/default.aspx) to the Root (/)'/><author><name>Steve Wortham</name><uri>http://www.blogger.com/profile/06878642454235403792</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://1.bp.blogspot.com/_uAFGogqHOtg/S6QHMLtiSMI/AAAAAAAAANw/8P82o2LWIkQ/s1600-R/SteveWortham.jpg'/></author><thr:total>22</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6437009486382609650.post-7196476458564772407</id><published>2008-06-30T19:32:00.015-05:00</published><updated>2008-09-18T16:31:18.217-05:00</updated><title type='text'>"Give and You Shall Receive" - A Guide to Improving Your Website</title><content type='html'>There's no doubt marketing companies have a tough job with websites.  They're called upon to drive more traffic to your site and/or improve conversion rates or sales.  These days there are marketing companies who specialize in all of this and even perform search engine optimization (SEO) services as well.  And SEO has been a growing industry in recent years.  The goal of an SEO company is to improve your placement in the search engines.  Of course, Google has such an overwhelming presence that you could call the process "Google optimization," but I digress.  &lt;br /&gt; &lt;br /&gt;SEO involves following best practices with html page design.  Google looks at many factors to determine relevance.  But in no particular order the 4 major factors are: &lt;br /&gt;1.) Page titles (anything inside the &amp;lt;title&amp;gt;&amp;lt;/title&amp;gt; tags)&lt;br /&gt;2.) URL's&lt;br /&gt;3.) Meta keywords and description&lt;br /&gt;4.) Content&lt;br /&gt;&lt;br /&gt;So you should use: &lt;br /&gt;1.) unique titles for every page&lt;br /&gt;2.) page names that are relevant to the page's content&lt;br /&gt;3.) meta keywords and meta description that describe the page's content&lt;br /&gt;4.) text and text links throughout the site (relying on text more than images)&lt;br /&gt;&lt;br /&gt;The problem I've seen is that the approach towards SEO can sometimes get a little out of hand.  I've seen examples where multiple pages are created on a site with very, very similar content with only slightly different wording.  The whole reason for creating these near-duplicate pages is to saturate the site with keywords (what the users are searching for to find your site).  The problem then is that these redundant pages seem strangely out of place to any human looking at the site.  This is just one form of SEO "trickery" I've seen that can detract from the user's experience when they're actually trying to read the content on your site.&lt;br /&gt; &lt;br /&gt;OK, let's say that you have good placement on the search engines but you want to improve your conversion rate.  In the case of an e-commerce site, a sale can be synonomous with a conversion.  Or in the case of a site for insurance, completing an online application could be defined as a conversion.  In either case a user starts out looking through the site.  Perhaps they'll read a few of your pages, or perhaps they won't.  And then, if you have it your way, they eventually perform the action you're wanting them to.  There's a science behind improving the conversion rate.  Often times a marketing company will suggest A/B testing to test if a change shows in improvement in the statistics.  The problem I've seen is we can sometimes become so obsessed with the conversion rate that we don't want to do anything to screw it up.  We don't want to scare off users, and sometimes we'll even lie or we don't tell them the truth up front in effort to get the user to do what we want.  And on top of that, some of the decisions around trying to optimize conversion rate can negatively influence the usability of the site.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;My Way or the Highway&lt;/strong&gt;&lt;br /&gt;So here's my proposition, and it's simple: Give and you shall receive.  In other words, often times what is best for the user is also best for you.  By this point, the article may read as if I'm saying that SEO and marketing services are evil.  And I certainly don't mean that, but this is a reminder that your priority should always be to make your customer happy.  And you may have to remind your marketing division of this too.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Write Compelling Content&lt;/strong&gt;&lt;br /&gt;My advice is to write lots of useful content or articles related to your website's goals.  If you sell cookbooks, write up some free recipes to bring people to your site.  If you're selling some sort of fitness program, write a detailed synopsis and free advice that your audience can benefit from.  This will give your company credibility and provide a good service to the public.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Design Carefully for Good Usability&lt;/strong&gt;&lt;br /&gt;Also focus on usability patterns and apply them to your site.  It should be easy to find information on your site, easy to find products, and especially easy to buy a product or complete an application.  Use your common sense in all of this, but also try user testing and as simple as it seems try basing your design on proven formulas in some of the hugely popular websites out there.  For example, users are accustomed to using sites like amazon.com, buy.com, hrblock.com, etc.  So you can take elements or ideas from their design and implement them in a similar fashion for your own site.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The Benefits&lt;/strong&gt;&lt;br /&gt;Never underestimate the power of a happy customer.  One of the big benefits of my suggestions is that users tend to link to "good" websites.  And the more links you have from other sites, the better link popularity you'll have.  Link popularity is the other major factor in search engine placement.  If your site is linked to from hundreds of other websites, then your chance of showing up on the first page of the search results can become far better.  In the user's mind a "good" website may be one with good products, good prices, good information, good service, or maybe all of the above.  But if you &lt;strong&gt;give&lt;/strong&gt; your users a good overall experience at your website, you will &lt;strong&gt;receive&lt;/strong&gt; more traffic and higher conversion rates.  So &lt;em&gt;that&lt;/em&gt; is what we as website owners should strive for.&lt;br /&gt;&lt;br /&gt;Below are a couple of valuable resources to help you get started:&lt;br /&gt;&lt;br /&gt;Website Optimization ( &lt;a href="http://www.websiteoptimization.com/" target="_blank"&gt;www.websiteoptimization.com&lt;/a&gt; ) - This site is packed with good information on optimizing your website for speed, but also information regarding SEO and usability.&lt;br /&gt;&lt;br /&gt;Jakob Nielsen's website ( &lt;a href="http://www.useit.com/" target="_blank"&gt;www.useit.com&lt;/a&gt; ) - Jakob is an authority in the web world when it comes to usability studies.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6437009486382609650-7196476458564772407?l=swortham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swortham.blogspot.com/feeds/7196476458564772407/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6437009486382609650&amp;postID=7196476458564772407' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/7196476458564772407'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/7196476458564772407'/><link rel='alternate' type='text/html' href='http://swortham.blogspot.com/2008/06/give-and-you-shall-receive-guide-to.html' title='&quot;Give and You Shall Receive&quot; - A Guide to Improving Your Website'/><author><name>Steve Wortham</name><uri>http://www.blogger.com/profile/06878642454235403792</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://1.bp.blogspot.com/_uAFGogqHOtg/S6QHMLtiSMI/AAAAAAAAANw/8P82o2LWIkQ/s1600-R/SteveWortham.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6437009486382609650.post-1344772365453811549</id><published>2008-02-05T13:24:00.000-06:00</published><updated>2008-02-05T13:50:26.504-06:00</updated><title type='text'>NSIS: Another Gem from Nullsoft</title><content type='html'>I figure I'll follow a bad review with a good one.  &lt;br /&gt;&lt;br /&gt;&lt;a href="http://nsis.sourceforge.net/Main_Page"&gt;NSIS&lt;/a&gt; is a scriptable installation system designed to create Windows installers.  It's open-source, free, and becoming more and more popular as time goes on.  Google uses it for many of their software applications, as does Yahoo, McAfee, Amazon, etc, etc.  You can find a list of more companies using it &lt;a href="http://nsis.sourceforge.net/Users"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I used NSIS to create the installer for a certain VB.NET software application I've been developing and supporting since 2004.  But NSIS wasn't my first choice.  In fact my first choice was InstallShield because that's what the consulting company I was working for at the time had used in the past. I wrote about 20 different installers with it, and they worked pretty well, some of the time.  But eventually I got fed up with InstallShield's awful support for what I considered simple custom tasks. When I eventually figured out how to do some of what I wanted, I still faced problems with InstallShield's flaky behavior.&lt;br /&gt;&lt;br /&gt;I was determined to find a replacement for InstallShield, so I looked at WISE. It was also a disappointing experience for me as the IDE itself liked to crash on me from time to time as many others have reported.  So WISE was out.&lt;br /&gt;&lt;br /&gt;I tried a few other installers and eventually I came to NSIS. At first I was skeptical since it was free, open-source, and I hadn't heard of it before. I figured that a free open-source installer like this couldn't possibly compete with the likes of InstallShield and WISE which seem to be regarded as industry standards for some reason.&lt;br /&gt;&lt;br /&gt;The thing is, using NSIS is a COMPLETELY different experience from InstallShield and WISE because absolutely everything is done through scripting which can seem like a daunting task at first. But I used the HM NIS Edit tool to build my first NSIS installer. The wizard took me through the basic steps of creating my first installer, and it wrote the code I needed to get started. The code was a little weird at first but I'm a programmer so I got the hang of it eventually. Furthermore, I found the user-submitted code examples and tutorials on their sourceforge site to be very helpful.&lt;br /&gt;&lt;br /&gt;I was able to do EVERYTHING I wanted with NSIS. I've been using it on a fairly large scale now for the past 3 years. And I've had absolutely no complaints with flaky behavior from thousands of users now. In the latest release of our completely rewritten software I made the installer first automatically detect if Windows Installer 3.1 is installed, and then download &amp; install it if necessary. Then it'll check if .NET 2.0 (or later) is installed on the machine and download it from Microsoft if it's not. It will also perform a CRC check to ensure the installer itself is not corrupt, assign appropriate file associations for the software, and check if the logged in user has administrative privileges. All of this works perfectly.&lt;br /&gt;&lt;br /&gt;On top of that, the final executable NSIS produces is much smaller than an equivalent InstallShield exe. And an NSIS installer performs the installation MUCH faster than InstallShield as well.&lt;br /&gt;&lt;br /&gt;So for me it was a no brainer. Once I got over the initial learning curve of NSIS I never looked back. I highly recommend it for any programmer who wants to build good Windows Installer packages for their software.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6437009486382609650-1344772365453811549?l=swortham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swortham.blogspot.com/feeds/1344772365453811549/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6437009486382609650&amp;postID=1344772365453811549' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/1344772365453811549'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/1344772365453811549'/><link rel='alternate' type='text/html' href='http://swortham.blogspot.com/2008/02/nsis-another-gem-from-nullsoft.html' title='NSIS: Another Gem from Nullsoft'/><author><name>Steve Wortham</name><uri>http://www.blogger.com/profile/06878642454235403792</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://1.bp.blogspot.com/_uAFGogqHOtg/S6QHMLtiSMI/AAAAAAAAANw/8P82o2LWIkQ/s1600-R/SteveWortham.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6437009486382609650.post-3721513663669702193</id><published>2008-02-05T13:12:00.000-06:00</published><updated>2008-02-05T13:55:14.880-06:00</updated><title type='text'>Adobe Acrobat Hell</title><content type='html'>Ever tried to use Adobe Acrobat Professional as a word processor?  If you have, you might have some idea of what this post is about.  I had to make a very very simple change to an existing PDF and it took me an hour to figure out how to do it without screwing up the formatting of the whole document.  I ended up selecting the text I wanted to edit and I clicked "create artifact."  And then I was able to isolate elements of the document.  It was not obvious to me at all that I needed to do that.  I was just grasping at straws and found something that worked... kind of.  I still ended up screwing up the formatting a little bit, but it'll have to do.&lt;br /&gt;&lt;br /&gt;Now I've never been too impressed with the user interface of most of Adobe's products.  I've always hated Acrobat Reader especially.  I think it's one of the most over-rated, over-used programs out there.  But man, this experience was beyond awful and this should have been such an easy task.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6437009486382609650-3721513663669702193?l=swortham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swortham.blogspot.com/feeds/3721513663669702193/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6437009486382609650&amp;postID=3721513663669702193' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/3721513663669702193'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/3721513663669702193'/><link rel='alternate' type='text/html' href='http://swortham.blogspot.com/2008/02/adobe-acrobat-hell.html' title='Adobe Acrobat Hell'/><author><name>Steve Wortham</name><uri>http://www.blogger.com/profile/06878642454235403792</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://1.bp.blogspot.com/_uAFGogqHOtg/S6QHMLtiSMI/AAAAAAAAANw/8P82o2LWIkQ/s1600-R/SteveWortham.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6437009486382609650.post-857924309341942137</id><published>2007-10-04T12:09:00.004-05:00</published><updated>2008-12-02T16:23:25.250-06:00</updated><title type='text'>Three ways to improve your website's speed</title><content type='html'>Other than the obvious server and connection upgrades, there are in fact a lot of optimizations that could be made to your average website and web server configuration to serve up websites faster and save bandwidth.&lt;br /&gt;&lt;br /&gt;There are 3 main points:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;1.) Code optimization&lt;/strong&gt; - In my opinion, optimization should always start at the code.  In this day and age of incredible processing speeds and high-bandwidth internet connections, underlying efficiency often goes overlooked.  But it shouldn't have to be that way.  People are just as impatient now as they ever were and a slow and unresponsive online experience is a sure way to scare off users.&lt;br /&gt;&lt;br /&gt;I suggest using an external CSS file to consolidate common formatting rules for your site.  Likewise, use external JS files for any commonly used javascript functions.  The benefit of using external CSS and JS files rather than inline code is that external files like these can be downloaded once and cached for the duration of a user's visit.&lt;br /&gt;&lt;br /&gt;Also use short-hand CSS when possible, and try to make efficient use of CSS in general.  Well-defined CSS rules can often make a substantial impact on cleaning up and shrinking your HTML files that would otherwise be packed with redundant formatting code.  &lt;br /&gt;&lt;br /&gt;Remove extranneous whitespace in your HTML, Javascript, and CSS.  If you look for it, it's usually not hard to find extranneous whitespace.  Sometimes you'll see trailing spaces at the end of a line, or perhaps your indentation uses individual spaces.  But if you replace double-spaces with a single tab, that'll cut the amount of bytes for indentation in half.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;2.) Use caching wisely&lt;/strong&gt; - Cache, what a beautiful invention.  There's no doubt cache can speed up the web.  And you've probably seen how you can change your browser caching settings.  But what you may not realize is that you can also control the way cache is handled on other users' computers by changing settings at your web server.  In IIS it's called content expiration under the "HTTP Headers" configuration tab for a website.  And in Apache you can use the mod_headers module to achieve the same effect.  With either server what they can do is send special instructions via the Cache-Control HTTP header.  And there can be a variety of caching rules sent inside this header that the browser will understand at the other end.&lt;br /&gt;&lt;br /&gt;Now, by default Internet Explorer will cache files in its own temporary internet files directory, which is good.  But, behind the scenes it still queries the web server upon &lt;em&gt;every&lt;/em&gt; request to check if a file has been updated.  And all of these roundtrip checks add up when you have dozens of images on a page.  In this way Internet Explorer is a little like a child in the back seat asking, "Are we there yet?" or in this case, "Has this file been updated yet?"  It's these roundtrips or nagging questions that you can eliminate with special caching settings at your web server.  If you specify that a given file should expire 1 hour after it's initial download, then the browser knows to cache that file for an hour.  So behind the scenes it's telling Internet Explorer to shut up for an hour, and THAT is a beautiful thing.&lt;br /&gt;&lt;br /&gt;I suggest using content expiration like this to your advantage for any static content on your site.  At the very least this should include CSS, JS, and image files.  One easy way to do this is to make an "images" folder for your images and an "include" folder for your CSS and JS files.  Then you can simply configure content expiration or caching rules at the web server for those folders.  The benefits of this can be huge for both the server and the client.  If you configure this for an HTML page as well, then it's possible to re-visit that page within the time limit and have it instantly load the entire page from browser cache.  The result is an incredibly responsive site for repeat visitors.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;3.) HTTP Compression&lt;/strong&gt; - Much like zip-compression technology can drastically shrink a TXT file, HTTP Compression can drastically shrink the physical size of your content before it's transmitted to the user.  Gzip compression (the most popular of HTTP compression technologies) has been supported in browsers for a long time.  In fact, it dates back to the IE4 days.  But even in the rare case that someone uses a browser that doesn't support it, the web server will be smart enough to send the data uncompressed.  The only real penalty is that it takes a little more processing power to compress the files.  But in the vast majority of cases CPU time is abundant but bandwidth is not.  So these days it's almost silly not to use compression.  Gzip compression can shrink your HTML, CSS, and JS pages down to 1/3 or sometimes 1/4 the size prior to transferring to the user's browser.&lt;br /&gt;&lt;br /&gt;Below are a few excellent resources for those of you who want to learn more about these techniques and how to implement them:&lt;br /&gt;- &lt;a href="http://www.port80software.com/support/articles/webperformance"&gt;Fundamentals of Web Site Acceleration&lt;/a&gt;&lt;br /&gt;- &lt;a href="http://www.mnot.net/cache_docs/"&gt;Caching Tutorial for Web Authors and Webmasters&lt;/a&gt;&lt;br /&gt;- &lt;a href="http://weblogs.asp.net/owscott/archive/2004/01/12/57916.aspx"&gt;IIS Compression in IIS6.0&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6437009486382609650-857924309341942137?l=swortham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swortham.blogspot.com/feeds/857924309341942137/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6437009486382609650&amp;postID=857924309341942137' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/857924309341942137'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/857924309341942137'/><link rel='alternate' type='text/html' href='http://swortham.blogspot.com/2007/10/three-ways-to-improve-your-websites.html' title='Three ways to improve your website&apos;s speed'/><author><name>Steve Wortham</name><uri>http://www.blogger.com/profile/06878642454235403792</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://1.bp.blogspot.com/_uAFGogqHOtg/S6QHMLtiSMI/AAAAAAAAANw/8P82o2LWIkQ/s1600-R/SteveWortham.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6437009486382609650.post-4491581162350802613</id><published>2007-09-27T13:35:00.000-05:00</published><updated>2007-09-28T16:37:26.511-05:00</updated><title type='text'>The perils of being responsible for a big website</title><content type='html'>I maintain and develop a website for an insurance agency.  All of our new business starts by someone coming to the website to fill out our online application.  So naturally when something goes wrong with the site there's a lot of responsibility on my shoulders.&lt;br /&gt;&lt;br /&gt;Now, for the past few days I've been preparing for a web server migration.  We were going to move the website and SQL database to a new dedicated server in a datacenter.  This morning was the set day to do the big move.  I planned everything ahead of time very carefully.  I wanted to minimize the downtime and this article was a big help: http://www.sqlservercentral.com/articles/Administering/2688/&lt;br /&gt;&lt;br /&gt;The plan was this:&lt;br /&gt;1.) Perform a complete backup of the database&lt;br /&gt;2.) Restore the complete backup onto the new server with NORECOVERY&lt;br /&gt;3.) Take down the online quoting process on the site for everyone except for my IP (for testing purposes), and change the connection string to point to the new server&lt;br /&gt;4.) Perform a differential backup of the database&lt;br /&gt;5.) Restore the differential backup with NORECOVERY&lt;br /&gt;6.) Restore the differential backup with RECOVERY&lt;br /&gt;7.) Test the site and if everything is OK then bring the site back online (still on the old server at this point)&lt;br /&gt;8.) Change the DNS settings&lt;br /&gt;&lt;br /&gt;I had tested all of this ahead of time and determined that we should be able to limit the downtime to just about 3 minutes.  I don't migrate websites often so I thought I was the man for getting it down to just 3 minutes of downtime.&lt;br /&gt;&lt;br /&gt;Well when it finally came down to it the migration didn't go as smoothly as I was hoping.  Apparently the production server was set up to block all IP addresses except for those explicitly allowed in an exception list.  And in the exception list was the IP I was testing from.  So of course my testing worked but when it was pushed to production, it didn't.  I didn't know the server had been configured that way and it took me awhile to figure that out. So as a result we had closer to two hours of downtime for the users that still had cached DNS.  Realistically, most users wouldn't have had cached DNS so most users visiting the site during that window of time would have seen the site from the new web server.  But still -- that sucked.&lt;br /&gt;&lt;br /&gt;The good news is everything is configured properly now.  The new web server is on a connection with more bandwidth than the old server.  And it's a quad-core machine with 4GB of RAM.  So it has the power to support us and then some.  I also configured it to use HTTP compression (which we didn't have on the old server) and the impact of that can be pretty huge when it comes to download times.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6437009486382609650-4491581162350802613?l=swortham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swortham.blogspot.com/feeds/4491581162350802613/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6437009486382609650&amp;postID=4491581162350802613' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/4491581162350802613'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/4491581162350802613'/><link rel='alternate' type='text/html' href='http://swortham.blogspot.com/2007/09/perils-of-being-responsible-for-big.html' title='The perils of being responsible for a big website'/><author><name>Steve Wortham</name><uri>http://www.blogger.com/profile/06878642454235403792</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://1.bp.blogspot.com/_uAFGogqHOtg/S6QHMLtiSMI/AAAAAAAAANw/8P82o2LWIkQ/s1600-R/SteveWortham.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6437009486382609650.post-6510089153949880587</id><published>2007-09-14T16:16:00.002-05:00</published><updated>2010-11-22T22:16:16.868-06:00</updated><title type='text'>Winamp: Sometimes the small companies do it best</title><content type='html'>I've used &lt;a href="http://www.winamp.com"&gt;NullSoft's Winamp&lt;/a&gt; as my music player of choice for years.  It's a free lightweight media player and it does what it does very well.  I've never seen it crash.  It has always been responsive and quick to start up.  And it has an easy-to-use EQ which I always configure to my liking for a particular computer and speaker setup.&lt;br /&gt;&lt;br /&gt;Over the years many other media players have come along and they have evolved.  Some will automatically download album art when you put in a CD, and they certainly have a lot of other "neat" features.  Although honestly I found most of it was extra fluff that I didn't need.  Winamp, on the other hand, has taken on many updates and revisions but it's strength is still the fact that it's a simple, efficient, and easy to use music player.  I love the fact that Nullsoft has &lt;i&gt;not&lt;/i&gt; turned it into bloatware.&lt;br /&gt;&lt;br /&gt;For some reason, for a little while I was using one of Winamp's rivals, Windows Media Player on my work computer.  I'll tell you what, it's like comparing a 2,000 pound Lotus Exige to a plump 3,500 pound Mustang GT.  Winamp is just so "lightweight" and quick to respond to my every request.&lt;br /&gt;&lt;br /&gt;Digging deeper I uncovered a shocking difference between the two players.  For those of you who like numbers, I ran each one to see how much memory each player would consume while simply playing an MP3 (no visualizations), and running Winamp in "classic" mode.&lt;br /&gt;&lt;br /&gt;Here are the results:&lt;br /&gt;Winamp 5.35: &lt;strong&gt;7,608 KB&lt;/strong&gt;&lt;br /&gt;Windows Media Player 11: &lt;strong&gt;66,508 KB&lt;/strong&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6437009486382609650-6510089153949880587?l=swortham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swortham.blogspot.com/feeds/6510089153949880587/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6437009486382609650&amp;postID=6510089153949880587' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/6510089153949880587'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/6510089153949880587'/><link rel='alternate' type='text/html' href='http://swortham.blogspot.com/2007/09/winamp-sometimes-small-companies-do-it.html' title='Winamp: Sometimes the small companies do it best'/><author><name>Steve Wortham</name><uri>http://www.blogger.com/profile/06878642454235403792</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://1.bp.blogspot.com/_uAFGogqHOtg/S6QHMLtiSMI/AAAAAAAAANw/8P82o2LWIkQ/s1600-R/SteveWortham.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6437009486382609650.post-213054705138909859</id><published>2007-08-02T16:53:00.001-05:00</published><updated>2010-11-22T22:17:41.394-06:00</updated><title type='text'>Removing Norton SystemWorks causes problems with Office Automation</title><content type='html'>This was a tough problem to uncover... so tough that I think it really should be documented. I develop and support some VB.NET 2.0 software which uses Microsoft Word Automation. One user sent me an email with a problem that occurs on his machine when this Word Automation functionality takes place.&lt;br /&gt;&lt;br /&gt;This is the error as it was reported:&lt;br /&gt;&lt;blockquote&gt;System.IO.FileNotFoundException: Retrieving the COM class factory for component with CLSID {000209FF-0000-0000-C000-000000000046} failed due to the following error: 8007007e.&lt;/blockquote&gt;&lt;br /&gt;I didn't know what was going on but my first suggestion was to try a Word "Detect and Repair." This didn't solve the problem. So I was left to searching Google for potential solutions. I was researching and researching for a couple hours and my hopes were fading.&lt;br /&gt;&lt;br /&gt;Then I found something. I found a case where somebody had to manually remove Norton Antivirus, but Norton left behind a registry entry with a bad reference. In this case this bad reference also caused a problem with Office Automation.  I thought I might be onto something here.  So I asked the user I was trying to help about this and sure enough, he too had Norton installed at one point but had since removed it. At this point I was feeling a bit like Dr. House diagnosing complex medical problems in the show conveniently named, "House."&lt;br /&gt;&lt;br /&gt;This user seemed very comfortable with his computer so I asked him to go to the following location in his registry and export and email it to me:&lt;br /&gt;&lt;blockquote&gt;\HKEY_CLASSES_ROOT\CLSID\{000209FF-0000-0000-C000-000000000046}\&lt;/blockquote&gt;&lt;br /&gt;The settings here are critical to the operation of Microsoft Word. So I took a good look at his registry settings and found the registry entry of consequence resides at:&lt;br /&gt;&lt;blockquote&gt;\HKEY_CLASSES_ROOT\CLSID\{000209FF-0000-0000-C000-000000000046}\InprocServer32&lt;/blockquote&gt;&lt;br /&gt;The (Default) string in this location was "C:\\Program Files\\Common Files\\Symantec Shared\\Script Blocking\\ScrBlock.dll". I had the user double check to ensure that this dll doesn't exist in that physical location. It didn't so I had him right-click that (Default) value and delete it. This solved the problem!&lt;br /&gt;&lt;br /&gt;Now apparently Norton can be notoriously difficult to remove completely. I had problems with this myself last year. I don't know if it's typical, or if it only happens when your computer happens to be infected and your Norton installation is crippled, or just what. But in this case it obviously left behind stray information which caused this problem.&lt;br /&gt;&lt;br /&gt;Hopefully what I've learned today will be helpful for someone else.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6437009486382609650-213054705138909859?l=swortham.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://swortham.blogspot.com/feeds/213054705138909859/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6437009486382609650&amp;postID=213054705138909859' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/213054705138909859'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6437009486382609650/posts/default/213054705138909859'/><link rel='alternate' type='text/html' href='http://swortham.blogspot.com/2007/08/removing-norton-systemworks-causes.html' title='Removing Norton SystemWorks causes problems with Office Automation'/><author><name>Steve Wortham</name><uri>http://www.blogger.com/profile/06878642454235403792</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='17' src='http://1.bp.blogspot.com/_uAFGogqHOtg/S6QHMLtiSMI/AAAAAAAAANw/8P82o2LWIkQ/s1600-R/SteveWortham.jpg'/></author><thr:total>3</thr:total></entry></feed>
