Thursday, February 28, 2008

set @variable then select @variable = no rows

here’s a strange one that came up the other day. if you have the following sql statement:

DECLARE @AppId INT

SET @AppId = 1

SELECT @AppId = 2

WHERE 0 = 1 --i.e. a condition that forces an empty recordset to be returned

SELECT @AppId

since @AppId was selected from a table with no rows (WHERE 0 = 1), i was expecting it to be NULL after this executes… but it turns out that the variable maintains its value from the SET call , so it’s 1. just an unexpected side effect to be aware of--

Tuesday, February 26, 2008

web service response caching: CacheDuration property doesn't work

if you want to cache the results from a web service call on the server, you’d think you just set the CacheDuration property the way you can with aspx pages (i.e. [WebMethod(CacheDuration=5)] and everything would be happy. turns out... no.
  • web service output is NEVER cached for http-post web service requests, so you have to use http-get, which is disabled by default for web services and enabling it is not a recommended practice. great.
  • browsers can stipulate “no-cache” in their request header, and the server will ignore its own cache for these requests. so even once you get http-get caching working, Firefox requests force the server to ignore its cache.

why this isn’t configurable on the server, i have no idea, but the short of it is: if you want real control over web service output caching, don’t use CacheDuration (i.e. write it yourself using Context.Cache, Application[] variables, or static variables). Context.Cache is a very cool class; you can specify an absolute expiration date, or dependencies on the cached content, so that the item is cleared from the cache when a dependency changes, or a sliding expiration date, like “5 seconds from last access”—

Thursday, February 21, 2008

beware of flash

sorry for the rant, but a couple of things came up today that wasted hours of time for me and are worth filing away in your flash development mental compartment.

adobe releases new flash builds frequently:

you can see what version of flash you have installed here: http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_15507

so what, you say? well, i mention this because i encountered a nasty bug with specific versions of flash 9 and ExternalCallback today. ExternalCallback is the interface that makes it easy to call from javascript into a flash movie. the bug is this: in IE, when a flash movie is inside a <form> tag, a cached flash movie is not properly re-loaded when it is pulled from the cache, and ExternalCallback just stops working. the bug was present or introduced at some point up to 9.0.44.0, but fixed by 9.0.115.0 (so i didn’t see it at first).

the fix (hack, really), is to append a unique querystring value to the .swf filename, so that IE never pulls the movie from the cache. this was acceptable in my case (an 8kb flash movie), but obviously wouldn’t have worked if the movie was larger.

another bug that was present in earlier versions of flash 9 caused IE to crash when a flash object was unloaded as the browser quit. the fix for that is just as nasty; get a load of this:



function cleanUpCounterObjects()
{
var objects = document.getElementsByTagName("object");

for (var i=0; i < objects.length; i++)
{
for (var x in objects[i])
{
if (typeof objects[i][x] == 'function')
objects[i][x] = null;
}
}
}

beforeUnloadCounterObjects = function()
{
//fix for memory bug with flash 9 and IE
__flash_unloadHandler = function(){};
__flash_savedUnloadHandler = function(){};

window.attachEvent( "onunload", cleanUpCounterObjects );
}

if (window.attachEvent)
window.attachEvent( "onbeforeunload", beforeUnloadCounterObjects);

i get it that cross-browser, cross-platform is hard to do, but doing flash development right is almost impossible with adobe’s versioning strategy. seems to me that side-by-side installations would solve all of these problems; developers could say “flash 9.0.45.0 only”, and when users update to 9.0.115.0, they actually just install it side-by-side with 9.0.45.0, so apps released for 9.0.45.0 continue to run in 9.0.45.0! or am i missing something?

again, just make sure you do as much testing as possible in different configurations. you can download older flash versions from adobe here:

http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_14266&sliceId=1

and the flash uninstaller is here:

http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_14157

good luck…

remember IE6

kind of goes along with the 1024x768 note: IE6 still accounts for 40% of our IE visits, and IE as a whole accounts for 80% of site visits. this means about 1 in 3 of all site visitors see what we do using IE6. this # is declining, but it’s still very much in play for now, so remember to check your work in IE6 in addition to IE7/Firefox. unfortunately, there are subtle differences in the IE rendering engines, and some things that work fine in IE7 just don’t in IE6.

when Firefox 3 comes out (fairly soon), we’ll have yet another browser to add to the make-sure-you-test-on list; ahhh, web development J

Wednesday, February 20, 2008

when doing GUI work, run your second monitor at 1024x768

remember that most of the world sees things very differently than we do, so make sure you frequently check your GUI work on a 1024x768 display; it’s still half of users. recent stats from our site:

1

1024x768

47.56%

2

1280x800

16.57%

3

1280x1024

10.05%

4

800x600

8.81%

5

1440x900

5.05%

Thursday, February 14, 2008

beware a Deleted flag on tables

some of our tables have a 'Deleted' flag, and a row cannot be considered to really be in a table unless the Deleted flag = 0. this means your joins will always have something like "t1.Id = t2.Id AND t1.Deleted = 0".

the design goal here was to keep some historical record of changes without the hassle of a history table, but it was really a bad idea since it’s way too easy to forget about when writing queries, and all indexes are irrelevant unless they start with the Deleted bit...

Thursday, February 7, 2008

vista shadow copies just saved me

vista keeps shadow copies of files and folders when it creates its daily restore points. so if you delete something accidentally, right-click on the folder and go to the “Previous Versions” tab; you can browse through the contents of the folder as it existed at the last restore point. there’s no fancy gui and you only get the last 2 restore points, but it got the job done--

Monday, February 4, 2008

chaining the C# ?? Operator

?? operator was news to me, Rick Stahl's blog is great: http://www.west-wind.com/weblog/posts/236298.aspx. snippet:

string value1 = null;
string value2 = "Test1";
string result = value1 != null ? value1 : value2;

which causes result containing Test1 or the second value.

In C# you can shortcut this special null comparison case with the new ??:

string result = value1 ?? value2;