Geeks With Blogs
Chris Falter .NET Design and Best Practices

The marketing gurus at Microsoft singlehandedly support a half dozen Starbucks franchises, no doubt, as they prime their adrenaline pumps to concoct Yet Another Plug (YAP) for the virtues of the .NET Framework.  "Write more functionality with 80% less code!", they shout.  As a heartfelt idealist, I take these claims seriously, so I have been looking for evidence to support the yapping.  Recently, I achieved a wondrous breakthrough that will cheer the Redmond lads and lassies and leave the Java crowd groaning in dismay.  Yes, folks, with exactly ZERO lines of code I have produced a programming construct that formerly required at least a few lines of procedural code.  And I am proud to say that it is a record that will never be broken; no one will ever create the same programming construct with less than zero lines of code, right?

Sidestep coding a data tier by binding SQL statements directly to a DataGridView control: that's pretty swift.  (Although for non-trivial applications I would not recommend it; I'll leave the details for another post.)  Avoid writing a WSDL interface for a web service by decorating a plain old programming interface with attributes and running a WSDL generation tool: what a concept!  But it takes genius, my friends-- yes, pure, unadulterated genius--to bequeath to the world a framework that allows the cunning programmer to create an infinite loop without any code whatsoever.  An infinite loop, effortlessly created with no code: who knew?

In the days before the .NET Framework, the tool-deprived, hard-working programmer actually had to write code to create an infinite loop.  Here's an interesting example from C++, which is of course the language in which all the Windows operating systems are written:

void RunLoop() {
  int i;
  i = 10;
  while (i > 0) {
    i = i--;

So how is this an infinite loop?  You just decrement i until it reaches 0, then you break out of the while loop, right?  Ha!  “i--” really means “i = i-1”, and it returns the pre-decrement value of i.  So when you assign i-- to i  the value of i never changes, and you just keep looping and looping and looping.  Doesn't this make you long for the good old days of C++, when you could write obscure bugs like this, or do pointer math that would allow you to modify data who-knows-where in the heap?  Of course, if you worked at Microsoft, you wouldn't have to long for the good old days, you could still be living them as you worked on Windows.  And you wondered why they have all those security bugs.

Now, though, the .NET-equipped, lazy programmer can write an infinite loop with no code at all and head home early.  Here's how:

1. Write an ASP.NET 2.0 application.  Configure the customErrors node in your web.config to redirect to an error page.

    <customErrors mode="On" defaultRedirect="Error.htm"/>

2. Put frames in error.htm, and let each frame contain an aspx page. 

3. Make a deployment error that causes all the aspx pages to break.  You could forget, for example, to tell your admin that the site is configured to JIT-compile the DLLs dynamically, and let him xcopy code-behind DLLS to the production website.

4. Pop open a frosty beverage and watch the fun when ASP.NET doesn't know how to deal with the multiple copies of the same class in the AppDomain.  It will detect an error on the home page, then redirect the browser to error.htm, just like the web.config tells it to.  The browser will then try to load aspx pages, and then ASP.NET will detect more errors and redirect the browser to error.htm again, so the browser will request the framed aspx pages again, which will cause ASP.NET to detect more errors yet again and redirect the browser to error.htm yet again, and so forth.  Just watch the status bar flash text like an old-timey stock ticker!  You never had such fun in the Pleistocene pre-.NET days.

If you want to spoil the fun and make things actually work, I would recommend that your user-friendly error.htm page never contain any .NET dependencies.  It should be pure browser-readable code; IIS should be able to pass it to the browser as is, without invoking anything related to the .NET Framework.  Of course, you could always ignore this advice in an attempt to tie my record for fewest lines of code to create an infinite loop.  But I'm not worried; I've created a record that can never be broken!

Here's hoping that the Microsoft marketing folks read this blog and get so excited that they storm the nearest Starbucks and run up a massive tab.

Posted on Friday, April 21, 2006 2:07 PM .NET Gotchas | Back to top

Comments on this post: Exceeding the Wildest Dreams of the Microsoft Marketing Department

# re: Exceeding the Wildest Dreams of the Microsoft Marketing Department
Requesting Gravatar...
Another favorite of mine along these lines...

Create an empty app_offline.htm file and add it to the root of your .Net application. Since it has no code it causes a bogus "Server error in '/Application' the resource cannot be found!". Difficult to debug if you don't look for the file :)

Left by Brian on Apr 21, 2006 5:12 PM

# re: Exceeding the Wildest Dreams of the Microsoft Marketing Department
Requesting Gravatar...
Actually, the server is doing the right thing in the above custom errors case, and doesn't crash (the redirects happen on the client not the server)....

It would be unwise to configure it that way, but I'm not sure I understand what you are proposing as an alternative behavior? How would ASP.NET know that you are pointing to a static .htm page that is in turn hosting a frame that is in turn calling back to the same site on the client to request a broken page?


Left by scottgu on Apr 21, 2006 5:52 PM

# re: Exceeding the Wildest Dreams of the Microsoft Marketing Department
Requesting Gravatar...
Also, I'd recommend using the remoteOnly option with <customErrors>. That means that the error page is only sent if the client connecting to it is remote. For local development you'll then see the error stack page to get details of the issue.


Left by scottgu on Apr 21, 2006 6:38 PM

# re: Exceeding the Wildest Dreams of the Microsoft Marketing Department
Requesting Gravatar...
Hey, I'm honored to have Scott Guthrie pay a visit! Scott, I think that ASP.NET could not do anything other than what it is doing. The point of my post is that, just as with C and C++, the .NET development environment can give you enough rope to hang yourself with, if you aren't careful. I also think that the .NET development environment is far, far superior to unmanaged C/C++, and has much less rope for the unsuspecting programmer. As for this specific issue, I would say it's the programmer's responsibility to make sure his/her error.htm page does not have any .NET dependencies.
Left by Chris Falter on Apr 25, 2006 1:33 PM

# re: Exceeding the Wildest Dreams of the Microsoft Marketing Department
Requesting Gravatar...
Perhaps the MS-provided default web.config page for a website should have a warning comment above the customErrors element that urges the developer to keep any ASP.NET dependencies out of the redirect page. And why not put a warning directly into the MSDN documentation for the customErrors element?
Left by Chris Falter on Apr 25, 2006 1:37 PM

# re: Exceeding the Wildest Dreams of the Microsoft Marketing Department
Requesting Gravatar...
A minor clarification: the deployment breaker that caused the error (which caused the redirect to error.htm, etc.) was that the 1.1 version of the code-behind assembly was left in the \bin directory when the new 2.0 site got deployed. So ASP.NET saw the same namespace/class in 2 assemblies in the bin directory, got confused, etc. This is an interesting side effect of the new ASP.NET compilation model, where it appends ~6 random character bytes to the name of the code-behind assemblies (and compiles one assembly per code-behind class, rather than one big assembly for the entire site). I'm not arguing that the new compilation model is bad, I'm just saying *be careful* when you convert a site from ASP.NET 1.1 to ASP.NET 2.0.
Left by Chris Falter on Apr 28, 2006 7:51 PM

Your comment:
 (will show your gravatar)

Copyright © Chris Falter | Powered by: