Scott Hanselman

Forcing an update of a cached JavaScript file in IIS

May 12, 2006 Comment on this post [12] Posted in ASP.NET | DasBlog | Javascript
Sponsored By

JavascriptcachingThis might seem obvious to some folks, but to others it's not, so it's worth mentioning. Regardless, it's a good example of a "white box" attitude. Don't assume. Always assert your assumptions with good tests.

A client wanted to know how to 'force' a client to update some javascript that the browser had cached. The easy answer is "change the file."

Here's what happens with a single HTML file and a single JavaScript file, running locally on my machine. The main directory is set to "Expire Immediately" via IIS's properties dialog. That means "keep it fresh."

Underneath the main directory is a directory called /js that is set to expire in 7 days, as seen at right.

Here's an abridged HTTP Header view (via ieHttpHeaders) after hitting the page for the first time ever important stuff in bold.

GET /javascriptcachingtest/default.htm HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.1)

HTTP/1.1 200 OK
Server: Microsoft-IIS/5.1
X-Powered-By: ASP.NET
Cache-Control: no-cache
Expires: Fri, 12 May 2006 19:03:59 GMT
Date: Fri, 12 May 2006 19:03:59 GMT
Content-Type: text/html
Last-Modified: Fri, 12 May 2006 18:53:33 GMT
ETag: "b01be5ef575c61:df3"
Content-Length: 115

GET /javascriptcachingtest/js/test.js HTTP/1.1
Referer:
http://localhost/javascriptcachingtest/default.htm
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.1)
Connection: Keep-Alive

HTTP/1.1 200 OK
Server: Microsoft-IIS/5.1
X-Powered-By: ASP.NET
Cache-Control: max-age=604800
Expires: Fri, 19 May 2006 19:03:59 GMT
Date: Fri, 12 May 2006 19:03:59 GMT
Content-Type: application/x-javascript
Last-Modified: Fri, 12 May 2006 18:54:28 GMT
ETag: "50b1c1d4f775c61:df3"
Content-Length: 151

Note that both files were returned with HTTP 200 OK and the Javascript file had a Last-Modified header returned and an Expires date a week in the future. Now I'll hit F5 to refresh.

GET /javascriptcachingtest/default.htm HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.1)

HTTP/1.1 200 OK
Server: Microsoft-IIS/5.1
X-Powered-By: ASP.NET
Cache-Control: no-cache
Expires: Fri, 12 May 2006 19:11:30 GMT
Date: Fri, 12 May 2006 19:11:30 GMT
Content-Type: text/html
Last-Modified: Fri, 12 May 2006 18:53:33 GMT
ETag: "b01be5ef575c61:df3"
Content-Length: 115

GET /javascriptcachingtest/js/test.js HTTP/1.1
Referer:
http://localhost/javascriptcachingtest/default.htm
If-Modified-Since: Fri, 12 May 2006 19:03:59 GMT
If-None-Match: W/"50b1c1d4f775c61:df3"
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.1)
Host: localhost
Connection: Keep-Alive

HTTP/1.1 304 Not Modified
Server: Microsoft-IIS/5.1
Date: Fri, 19 May 2006 19:03:59 GMT
X-Powered-By: ASP.NET
Cache-Control: max-age=604800
Expires: Fri, 19 May 2006 19:03:59 GMT
ETag: "50b1c1d4f775c61:df3"
Content-Length: 0

JavascripttouchNote that the JavaScript file wasn't return (Content-Length: 0), the ETag is the same, and instead a 304 Not Modified was returned. This is the essense of client side caching and is something you should be exploiting (Sadly, fewer folks than you think do this) to get good throughput, efficiency and save on bandwidth costs.

Now, I'll "touch" the file - change it's modified date using the touch.exe I've got in my c:\utils folder (from http://unxutils.sourceforge.net/). Of course, there are other ways to do this, but you get the idea.

We've touched the file, so we'll hit F5 again to refresh:

GET /javascriptcachingtest/default.htm HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.1)

HTTP/1.1 200 OK
Server: Microsoft-IIS/5.1
X-Powered-By: ASP.NET
Cache-Control: no-cache
Expires: Fri, 12 May 2006 19:11:30 GMT
Date: Fri, 12 May 2006 19:11:30 GMT
Content-Type: text/html
Last-Modified: Fri, 12 May 2006 18:53:33 GMT
ETag: "b01be5ef575c61:df3"
Content-Length: 115

GET /javascriptcachingtest/js/test.js HTTP/1.1
Accept: */*
Referer:
http://localhost/javascriptcachingtest/default.htm
Accept-Language: en-us
Accept-Encoding: gzip, deflate
If-Modified-Since: Fri, 12 May 2006 19:03:59 GMT
If-None-Match: "50b1c1d4f775c61:df3"
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.1)
Host: localhost
Connection: Keep-Alive

HTTP/1.1 200 OK
Server: Microsoft-IIS/5.1
X-Powered-By: ASP.NET
Cache-Control: max-age=604800
Expires: Fri, 19 May 2006 19:11:30 GMT
Date: Fri, 12 May 2006 19:11:30 GMT
Content-Type: application/x-javascript
Last-Modified: Fri, 12 May 2006 19:11:29 GMT
ETag: W/"804647dff775c61:df3"
Content-Length: 151

Notice that the browser asks for the JavaScript not only "by name" but also by date, and by ETag, a mostly unique identifier. The IIS server responds with an HTTP 200 OK, returning the freshly changed (in IIS's mind) file along with a new ETag and a new Last-Modified date.

As an aside, DasBlog does a pretty good job in its RSS Syndication Code of programmatically managing If-Modified-Since behavior. Remember that ASP.NET's <%OutputCache%> is SERVER-SIDE. It's not what we've just seen here. If you want this kind of behavior in your ASP.NET code, you'll need to do it manually in code. I'll post examples of that later.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Getting Things Done with SpeedFiler

May 11, 2006 Comment on this post [4] Posted in Reviews | Tools
Sponsored By

SpeedFilerOmar's turned me on to SpeedFiler, and I'm loving it.  I've talked about my personal system of organization before and my use of Getting Things Done.

In a nutshell, your Inbox is just that, your INbox. Not your "hold everything" box. If it's IN your INbox then it hasn't been processed. The basic processing rules are Do it, Drop it, Delegate it, or Defer it.

Everything else gets filed away for reference, and that's where SpeedFiler comes in. As with all useful niche utilities it is nicely priced at $19.95 (finally a company that understands pricing, unlike some.)

Outlook doesn't support "tagging" of Email messages (categories are a possibility, but they aren't very easy to set or search) so we have this big hierarchy of folders that typically run around in and drag-and-drop messages. Filing stuff isn't very quick if you're trying to bang through your inbox and get it down to zero messages.

MyoutlookfoldersSpeedFiler grabs Shift-Ctrl-V when a message is selected and pops up a dialog with the focus set to receive keyboard input immediately. So if I get a message that I want to blog about, I type:

Shift-Ctrl-V, @bl, Enter

and it's filed. As you're typing it looks up in the the list of folders an offers a list of folders that match you search string.

It's also got an unobtrusive toolbar that has dynamic buttons that change to show the names of the folders you've recently filed things to. That reduces filing to common areas down to one click.

There's a "Go To Folder" text box that you just type the name, or partial name, of a folder and hit enter and you're there.

I put an @sign at the beginning of a number of folders to make them group together. In the "pure" GTD world those are supposed to be "context" that I work in, like @home and @office, so I'm breaking the rules a bit. These contexts are more mental than physical but they work for me.

Some small complaints are there's a pause when Outlook starts up when SpeedFiler enumerates the folders. My folders don't change that much, not more than a few times a week, so if the program would just store the hierarchy in alternate storage and start up with that cached information, it could use a background thread to "catch up" later.

Itzy, the author of SpeedFilter has a blog called Email Overloaded.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

If you love your family and your kids, do not play Elder Scrolls IV: Oblivion - It's that good

May 11, 2006 Comment on this post [18] Posted in Reviews | Gaming
Sponsored By

Elder Scrolls Oblivion Screenshot of a HouseDarn that Phil Haack, he wrote a post on Oblivion as I was writing one on a plane yesterday. If I only had connectivity at 30,000 feet. 

The Elder Scrolls IV: Oblivion is simply one of the best role-playing games ever made. [GameSpot]

No lie, no joke, it's that good.

Others are having similarly disturbing experiences:

Because the game is so damned addictive that when you're not playing, you wind up looking outside and thinking "man, that lighting model is really realistic!" before you remember you're not actually playing at that particular moment.

Even my wife has sat and played it with me for upwards of 30 minutes, which is a huge accomplishment if you ask me. However, "playing" the game with Mo meant "going for a stroll and looking at the scenery" which is something that you can really do for hours. I walked up a mountain over the course of two days, as I did the sun went down, dusk came, then the stars came out, then it started to rain. As we go towards the top of the mountain it began to snow.

There's been so many amazing moments. Once I found an empty camp and decided to sleep there and left my horse outside. I was awakened by a bandit whose bed I was apparently sleeping in. He had already killed my horse, the evil bastard. There's been times I've met a character I'd seen before and he's said "Oh, you again. How are you?"

There's such a sense that you are a part of a larger world that will (and does) continue without you. I've literally watched fights break out in front of me in a bar when some guy decided to pickpocket another. It wasn't scripted, it just happened.

One aside, to the mad fools who paid $500 for a new video card just to play this game, or just bought a whole new machine, seriously, please, get an Xbox360. Playing Oblivion on a 40" HDTV is just amazing. It's never crashed, no problems at all. I would be pretty frustrated if it were crashing often on a PC as some folks are reporting. (Interestingly enough, I've never had Guildwars crash on my PC...)

If you're playing Oblivion, leave a comment about something amazing or surprising that you've seen while playing the game. Here's an article called 64 Most Amazing Oblivion Moments.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Hanselminutes Podcast 17

May 11, 2006 Comment on this post [2] Posted in Podcast | ASP.NET | XML | Tools
Sponsored By

HanselminutesMy seventeenth Podcast is up. This episode is all about syndication.

We're listed in the iTunes Podcast Directory, so I encourage you to subscribe with a single click (two in Firefox) with the button below. For those of you on slower connections there are lo-fi and torrent-based versions as well.

Subscribe to my Podcast in iTunes

Our sponsors are PeterBlum and the .NET Dev Journal.

As I've said before this show comes to you with the audio expertise and stewardship of Carl Franklin. The name comes from Travis Illig, but the goal of the show is simple. Avoid wasting the listener's time. (and make the commute less boring)

  • Each show will include a number of links, and all those links will be posted along with the show on the site. There were 23 sites mentioned in this episode, some planned, some not.
  • The basic MP3 feed is here, and the iPod friendly one is here. There's a number of other ways you can get it (streaming, straight download, etc) that are all up on the site just below the fold. I use iTunes, myself, to listen to most podcasts, but I also use FeedDemon and it's built in support.
  • Note that for now, because of bandwidth constraints, the feeds always have just the current show. If you want to get an old show (and because many Podcasting Clients aren't smart enough to not download the file more than once) you can always find them at http://www.hanselminutes.com.
  • I have, and will, also include the enclosures to this feed you're reading, so if you're already subscribed to ComputerZen and you're not interested in cluttering your life with another feed, you have the choice to get the 'cast as well.
  • If there's a topic you'd like to hear, perhaps one that is better spoken than presented on a blog, or a great tool you can't live without, contact me and I'll get it in the queue!

Enjoy. Who knows what'll happen in the next show?

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Playaway - Preloaded Portable Digital Audiobooks

May 10, 2006 Comment on this post [10] Posted in Reviews
Sponsored By

I've talked before about what a fan of Audible I am. Once you incorporate it in to your life by making it easy to listen in your car and you've got a nice rhythm for how many times you sync your iPod or MP3 player, it really enriches your life. I've even got my wife hooked on it. She walks three miles a day with the baby and has been listening to The Time Traveler's Wife (a fantastic book, highly recommended.)

I'm in Charlotte transferring planes to Dallas right now and just noticed a very clever digital device that I hadn't seen before. It's such a clever and totally obvious idea. Portable Audio Books with the audio pre-loaded on a "disposable" player.

They are called Playaway. Apparently they launched a year ago. They're attractively packaged and include everything you need. The book, pre-loaded batteries and headphones. The audio books are tiny, about the size of a micro-cassette with controls on the back for controlling the speed of the reader's voice, fast forwarding, etc.

Fantastic idea, brilliantly executed, save one thing. $39.95 for a book? Oy. I was a biscuit away from buying one, was drawn to the retail point of sale, picked it up, looked at the box, all the things one is supposed to do if the marketers got it right.

However, in this case, I turned the package over and blanched at $39.95. Some are even more. Yikes. If it were $19.95, sold, without even a thought. $24.95, maybe. $30, eh. $40? Hell no.

Back to audible again. For half the Playaway's cost per month I get two books. Sure I have to have an audio player, so I'm comparing apples to carburetors, but you get the idea. If a first class recent paperback is <$10, I expect a device like this to be under $25, IMHO. I'm sure the price will come down, but at this pricing it kind of squashed the whole impulse buy thing. Still a rockin' sweet idea though. Maybe I'll give some of these for Christmas to some of my Luddite relatives. :)

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.