Microsoft Velocity


I've always been surprised that Microsoft never offered a distributed caching mechanism out of the box.  Their built-in ASP.NET caching works well, but only on one box.  memcached can run on Windows boxes, but for all intents and purposes, you're on your own if you choose to implement it.  There is at least one third party product I know of that can fill this space, but it is quite pricey.  Today, at last, Microsoft has announced a project codenamed "Velocity" that will be their distributed caching story for .NET:

Project “Velocity” is a distributed in-memory application cache platform for developing scalable, available, and high-performance applications. “Velocity” fuses memory across multiple computers to give a single unified cache view to applications.

Even though I have no immediate use for distributed caching, I certainly see the need for it.  I can't wait to muck around with it and see what it can do.

author: Jon Sagara | posted @ Tuesday, June 03, 2008 12:33 PM | Feedback (0)

HttpValueCollection.ToString() generates your nice query strings


In an ASP.NET page, if you call Request.QueryString.ToString(), you'll get a nicely formatted query string back, like this:

 my=query&string=value&foo=bar

"That's nice," I thought.  "I wonder how they implemented it.  I'll fire up Reflector and take a look."

However, when you look at the declaration of QueryString in HttpRequest, you'll see that it is of type NameValueCollection, a class that has no ToString() override; at first glance, it looks like you'd simply be calling System.Object.ToString().

Obviously, this is not what is happening, so to find out how the query string is being generated, I had to dig just a little bit deeper.  Fortunately, VS2008 lets you step into the framework.

When you step in you'll see that HttpRequest.QueryString is indeed defined to be of type NameValueCollection, but when it actually gets instantiated, it is initialized to be of type HttpValueCollection, an internal class that derives from NameValueCollection. 

HttpValueCollection has a ToString() override that does the dirty work of constructing the nice query string that you see at the top of this post.

I'm so glad that Microsoft decided to allow us to step into the framework source code.  Otherwise, I probably would have spent a good hour trying to track down the magical NameValueCollection.ToString() call.

author: Jon Sagara | posted @ Saturday, May 24, 2008 8:43 PM | Feedback (0)

Why I buy eBooks whenever possible


I've recently started purchasing "eBooks" whenever possible because they are just so dang convenient.  I can easily share them between my different machines, so I no longer have to lug a bunch of heavy books back and forth between home and work.

That's an obvious benefit.

A really cool benfit, though?

If you buy from a forward-thinking publisher with great customer service, they'll do things like provide you an updated copy of the book that includes fixes and errata.  Here's an email I recently received from Manning Publications:

Dear Manning Customer,

You previously purchased the Ebook version of ASP.NET AJAX in Action from the Manning online store. Since that time the author has provided a few corrections and other errata that we have incorporated in an updated version. As a courtesy we are making the updated Ebook available to all who purchased the original. Below please find the link to download this updated version.

When's the last time a book publisher mailed you an updated version of your hard copy, just to distribute errata?

That is just so awesome, and totally unexpected.

Manning seems to be keeping up with the latest technologies, and the 3 books I have purchased from them have been worth their weight in gold.  I am a repeat customer, and if you're looking for tech books, I urge you to give them a shot.

author: Jon Sagara | posted @ Wednesday, May 21, 2008 10:27 AM | Feedback (0)

Response.Redirect and the ThreadAbortException, and why it’s a good thing


Note: The ASPX and code-behind files are available here.

A couple of months ago, I ran into a problem where I was seeing a bunch of ThreadAbortExceptions showing up in my logs.  It didn’t take long to track down why – I was calling Response.Redirect from within a try/catch block in my ASP.NET code-behind page, and the catch block was catching the ThreadAbortException and writing it out to the log.  But why was the ThreadAbortException being generated? 

It turns out that Response.Redirect, when called with just the URL, or with the URL and a Boolean value of true, calls the Response.End method.  Response.End then calls Thread.Abort on the current thread, and, assuming that the page is in a cancellable state, this method throws the ThreadAbortException, alerting the framework that it is time to stop this thread, and NOW.

Why is this a good thing?

Let’s step back a bit and look at the recommended workaround for dealing with the ThreadAbortException.  Googling for an answer yields many suggestions to call Response.Redirect and pass the Boolean value false as the second, optional parameter.  This effectively suppresses the ThreadAbortException, preventing it from being caught and potentially logged as an error.

All is well and good, right?  Isn’t this what we want?

Not quite.

One side-effect of suppressing the ThreadAbortException is that any code after Response.Redirect is still executed.  This includes any event handlers in the page lifecycle that have yet to execute.  This is a waste of system resources, particularly if any of these event handlers contains resource-intensive code.

For the sake of illustration, let’s assume that our page, Default.aspx, has event handlers for most of the Page’s events:

  • Page_PreInit
  • Page_Init
  • Page_InitComplete
  • Page_PreLoad
  • Page_Load
  • Page_LoadComplete
  • Page_PreRender
  • Page_PreRenderComplete
  • Page_SaveStateComplete

Let’s further assume that each of these event handlers contains a resource- and time-intensive operation.  It could be a database call, a network call, or a batch image manipulation.  Whatever it is, it requires a lot of resources and a lot of time.

Each event handler will append a string to a StringBuilder member variable called _EventsFired.  Immediately preceding the call to Response.Redirect, _EventsFired will be stored as a Session variable so that the error page, Error.aspx, can display which methods were called.  The Redirect will occur in the Page_Load method; the user will be sent from Default.aspx to Error.aspx, which will then display the contents of _EventsFired.

Here is the code listing of Default.aspx’s Page_Load event handler:

protected void Page_Load (Object sender, EventArgs e)

{

    _EventsFired.Append ("Page_Load called.  Resource-intensive operation executed.<br />");

 

    try

    {

        Session["ErrorMessage"] = _EventsFired;

 

        Response.Redirect ("Error.aspx", false);

        Context.ApplicationInstance.CompleteRequest ();

    }

    catch (Exception ex)

    {

        _EventsFired.Append (ex.ToString ());

    }

}

Notice how we are passing false as the second parameter of Response.Redirect, meaning that we will prevent a ThreadAbortException from being thrown. 

Here is the output from Error.aspx:

Page_PreInit called. Resource-intensive operation executed.
Page_Init called. Resource-intensive operation executed.
Page_InitComplete called. Resource-intensive operation executed.
Page_PreLoad called. Resource-intensive operation executed.
Page_Load called. Resource-intensive operation executed.
Page_LoadComplete called. Resource-intensive operation executed.
Page_PreRender called. Resource-intensive operation executed.
Page_PreRenderComplete called. Resource-intensive operation executed.
Page_SaveStateComplete called. Resource-intensive operation executed.
Render called.

Page execution did not stop at Page_Load, even though we told the Application to complete the request!  In all likelihood, this is not the desired behavior, especially if any of the post-Load event handlers contains time-consuming or resource-intensive operations.

Now let’s modify Default.aspx’s Page_Load event handler to call Response.Redirect without suppressing a ThreadAbortException from being thrown:

protected void Page_Load (Object sender, EventArgs e)

{

    _EventsFired.Append ("Page_Load called.  Resource-intensive operation executed.<br />");

 

    try

    {

        Session["ErrorMessage"] = _EventsFired;

 

        Response.Redirect ("Error.aspx");

    }

    catch (Exception ex)

    {

        _EventsFired.Append (ex.ToString ());

    }

}

Here is the output from Error.aspx (remember, this is the list of events that fired during the processing of Default.aspx):

Page_PreInit called. Resource-intensive operation executed.
Page_Init called. Resource-intensive operation executed.
Page_InitComplete called. Resource-intensive operation executed.
Page_PreLoad called. Resource-intensive operation executed.
Page_Load called. Resource-intensive operation executed.
System.Threading.ThreadAbortException: [snip] \Default.aspx.cs:line 45

It’s almost what we want, but notice that we “logged” the ThreadAbortException.  We need a way to exclude that from being logged. 

Let’s modify Default.aspx’s Page_Load event handler one more time:

protected void Page_Load (Object sender, EventArgs e)

{

    _EventsFired.Append ("Page_Load called.  Resource-intensive operation executed.<br />");

 

    try

    {

        Session["ErrorMessage"] = _EventsFired;

 

        Response.Redirect ("Error.aspx");

    }

    catch (System.Threading.ThreadAbortException)

    {

        throw;

    }

    catch (Exception ex)

    {

        _EventsFired.Append (ex.ToString ());

    }

}

Here is the output from Error.aspx:

Page_PreInit called. Resource-intensive operation executed.
Page_Init called. Resource-intensive operation executed.
Page_InitComplete called. Resource-intensive operation executed.
Page_PreLoad called. Resource-intensive operation executed.
Page_Load called. Resource-intensive operation executed.

Success!  Finally, the desired result!

  • The page stopped processing when it was supposed to, right after the call to Response.Redirect.
  • Event handlers later on in the page lifecycle were not unnecessarily executed.
  • The ThreadAbortException was not “logged” by our catch block.  Instead, it was explicitly caught and rethrown up the stack.

So there we have it.  Suppressing the Response.Redirect-generated ThreadAbortException can be a bad thing, particularly if there is a lot of resource-intensive code left to execute after the redirect.  To prevent those pesky ThreadAbortExceptions from showing up in our log files, all we have to do is explicitly catch them and rethrow them.  On busy sites, this can help to conserve scarce resources.

Used properly, ThreadAbortException is your friend.

Update 2007-08-01 07:44

Of course, I could have moved the Response.Redirect outside of the try/catch.  However, the code that prompted the writing of this article is legacy production code that can't be modified at my whim, hence the need for this approach.

Update 2008-04-05:  Moved over from jonsagara.com.

author: Jon Sagara | posted @ Saturday, April 05, 2008 8:28 PM | Feedback (0)

Nice job, Unnamed Financial Institution


So I just signed up for online access at my financial advisor's parent company's Web site.  During registration, I got this:

To their credit, I was actually able to sign back in and complete my registration without a hitch, but, still, I expect much more from a large financial institution that handles my investments.

author: Jon Sagara | posted @ Tuesday, March 11, 2008 4:45 PM | Feedback (0)

Microsoft's new customer retention strategy


(To be fair, I got this message while trying to close Excel when one of the cells had an invalid formula, so it's not as WTF-ey as it might seem.)

author: Jon Sagara | posted @ Tuesday, March 04, 2008 2:33 PM | Feedback (0)

CopySourceAsHtml in Visual Studio 2008


Ever since I upgraded from Visual Studio 2005 to 2008, I was kind of bummed because I thought I had lost support for CopySourceAsHtml.  If you're unfamiliar with CopySourceAsHtml, it allows you to copy your source code, style and all, from Visual Studio and paste it into an HTML document.  Observe:

class Program

{

    static void Main (String[] args)

    {

        Console.WriteLine ("Press ENTER to exit the application");

        Console.ReadLine ();

    }

}

Pretty slick, eh?

Unfortunately, as of this writing, the author of the tool hasn't yet updated it to work in Visual Studio 2008.

Well, the good news is that some smarty named Andreas Erben figured out how to get it to work in VS2008 without having to recompile anything.  You can read the steps on how to do it here.

Enjoy!

author: Jon Sagara | posted @ Saturday, March 01, 2008 8:37 PM | Feedback (0)

Hello!


Well, as you can see, this is my new blog.  My aim is to post helpful .NET nuggets along the way with the goal of helping people overcome the same obstacles that I have faced.

TTFN

author: Jon Sagara | posted @ Thursday, February 28, 2008 1:57 PM | Feedback (0)