The blog of dlaa.me

Three weeks since we shipped? Must be time to ship again! ["Atlas" Control Toolkit updated!]

As you may already know, we released the "Atlas" Control Toolkit a few weeks ago to almost universally positive feedback.

But it's hard to please everyone, and we got some negative feedback on our relative lack of support for Apple's Safari web browser. (Opera was mentioned, too, but it's another story that I may blog about some other day.) Contrary to the article's suggestion, we actively developed and tested our code on both IE 6 and Firefox 1.5; all nine controls worked in both browsers with two very minor exceptions due to specific limitations. However, we didn't have the time or resources to test with Safari, so our results for that browser were not very good. Sorry about that!

This time around, Safari support was a BIG priority. In fact, we probably spent more time with Safari than with IE or Firefox! Safari brings with it a number of peculiarities and unfortunately has not yet been a specific focus of the Atlas team (like us, they hadn't gotten around to implementing complete Safari support). So we started out at somewhat of a disadvantage. But a whole bunch of dedicated effort - and a variety of elegant (and some less-than-ideally-elegant) workarounds - have gotten us to the point where all but two of our controls work great on Safari! That's a pretty significant improvement for only three week's time during which we also fixed bugs, added new features, helped users on the "Atlas" Control Toolkit Forums, incorporated a bunch of their feedback, and added new documentation.

Oh, yeah, we also added *four* new controls to the Toolkit!! (Which all work flawlessly under Safari, by the way.) I'm happy to introduce the...

  • AlwaysVisibleControl: Docks any panel to the browser edge so it remains visible all the time!
  • DropShadow: Adds attractive drop shadows to any control on the page!
  • ModalPopup: Shows styled modal UI without using HTML dialogs!
  • RoundedCorners: Rounds the corners of any control for a clean, professional look!

The release notes for the latest version outline a bunch of other improvements we made in the past three weeks. Please take a minute or two to read about all the new stuff. And while you're at it, sample the new (and existing) controls on the web right now (no install required). Then go ahead and download the new Toolkit so you can start creating your own controls!

As always, if you have any feedback, please share it with us on the forum (or email me)!!

Next up: Enabling community submissions to the Toolkit... (Yum, it's going to be good!)

Good news is good news! [Coverage of the "Atlas" Control Toolkit release is favorable!]

I've been watching the web for coverage of the Agility Team's recent "Atlas" Control Toolkit release. Here are some of the links I've found so far:

I know I'm biased [ :) ], but the majority of the coverage so far seems to be positive! That's fantastic, but we know there are some rough edges, too. Fortunately, our friends on the "Atlas" Control Toolkit Forums are helping us identify and remedy any problems they find. If you tried the Toolkit out and had *any* difficulties, we'd love to hear about them on the Forum! (After all, we can't fix what we don't know about.)

Meanwhile, if you know of other links to coverage of the "Atlas" Control Toolkit, please share them with me!

Update: Added AJAX impact link passed on to me by reader Blake Handler.

Update: Added CRN and Register links.

ASP.NET and "Atlas" make AJAX easy [The Agility Team's "Atlas" Control Toolkit is available for download!]

The Agility Team is proud to announce the release of the "Atlas" Control Toolkit! Check out the "Atlas" Control Toolkit page for an overview of the project, a link to the demo web site where you can try out the samples, and a download so you can play around with everything yourself!

Particularly cool stuff that's worth calling out:

  • There are nine different sample controls that you can try right now from the comfort of your own browser!
  • It's really simple to add cool AJAX functionality to existing web sites by adding one of the Toolkit's controls to an existing page and hooking it up to existing page elements! No typing required!!
  • But don't take my word for it - check out the "Using a sample extender" walkthrough to see just how easy it is! (In fact, it's less work to add a control than it is to create the page in the first place!)
  • Creating your own custom controls is also easy, and the included AtlasControlExtender takes care of a bunch of the bookkeeping for you so that you're free to concentrate on the important stuff: adding neat functionality to your site!
  • Again, see how easy it is by reading the "Creating a new extender" walkthrough!
  • The source code to all the controls is part of the download and is being released under the Microsoft Permissive License (Ms-PL) which "... allows you to view, modify, and redistribute the source code for either commercial or non-commercial purposes."! You can do pretty much whatever you want with it!
  • Even better, we'll soon be opening the project up to the community so that *anyone* can add new controls and new features and everyone else can use them to make even better web pages! (More details coming soon...)

Still have questions? Find a problem? Have a cool suggestion? Great!! Go to the "Atlas" Control Toolkit Forum and let us know! We'll be hanging out there doing our best to answer any questions people have. This is an early preview release, so we expect to get lots of good questions and hear lots of fantastic suggestions. Don't be shy - we're looking forward to hearing from you!

ASP.NET is powerful. AJAX is hot. Atlas makes it easy. The AtlasControlToolkit makes it fun!!

When the GAC makes you gack (Part 2) [How something can be both IN and NOT IN the GAC at the same time]

In Part 1 we investigated a curious tool failure and discovered that it's possible for something to be both IN and NOT IN the GAC at the same time. The results of the investigation so far have been informative, but unrevealing. So let's try another approach...

The Sysinternals Filemon tool should let us see exactly where the tool is looking for vjslib.dll and maybe that will help figure out why it can't be found. Run Filemon, specify a filter of "*tool_name*" to limit the output, then run the program of interest. Filemon will capture a whole bunch of stuff, so save the output to a file where it can be searched more easily. We'll start with a simple string search for "vjslib" to see what turns up:

D:\Temp>findstr vjslib Filemon.LOG
327     6:58:10 PM      GACBlog.exe:212 QUERY INFORMATION       C:\WINDOWS\assem
bly\GAC_64\vjslib\2.0.0.0__b03f5f7f11d50a3a     PATH NOT FOUND  Attributes: Erro
r
328     6:58:10 PM      GACBlog.exe:212 QUERY INFORMATION       C:\WINDOWS\assem
bly\GAC_MSIL\vjslib\2.0.0.0__b03f5f7f11d50a3a   PATH NOT FOUND  Attributes: Erro
r
329     6:58:10 PM      GACBlog.exe:212 QUERY INFORMATION       C:\WINDOWS\assem
bly\GAC\vjslib\2.0.0.0__b03f5f7f11d50a3a        PATH NOT FOUND  Attributes: Erro
r
...

Oooh, that's interesting, there seem to be multiple GACs: GAC_64, GAC_MSIL, and GAC each get probed unsuccessfully. But we recall from Part 1 that gacutil told us vjslib was in the GAC, so what GAC is it in??

C:\WINDOWS\assembly>dir vjslib.dll /s
 Volume in drive C is C
 Volume Serial Number is 0C48-9782

 Directory of C:\WINDOWS\assembly\GAC_32\vjslib\2.0.0.0__b03f5f7f11d50a3a

2006-02-21  11:18 AM         3,661,824 vjslib.dll
               1 File(s)      3,661,824 bytes

     Total Files Listed:
               1 File(s)      3,661,824 bytes
...

Ah-ha! There's a fourth GAC, GAC_32, that contains the required assembly, but that GAC isn't getting checked when the tool is run and so the tool is failing.

At this point we can begin to guess that the problem is unique to my machine because I'm the only person who's trying to run the tool under a 64-bit OS. (Which also explains why most people won't have been able to reproduce this problem with the sample code in Part 1.) Now that we understand the problem a little better, we can pretty easily find more detailed information about what's going on by doing some quick web searching. In this case, Junfeng Zhang's post GAC, Assembly ProcessorArchitecture, and Probing explains the motivation behind multiple GACs.

Okay, so we've figured out what the problem is: the tool is compiled to be architecture-independent and the GAC probing sequence for architecture-independent programs on 64-bit OSes does not include the architecture-dependent 32-bit GAC where vjslib.dll is actually installed. The question now becomes how to fix the tool so that it will run successfully on both 32- and 64-bit OSes.

My first thought was to find out how to modify the probing sequence for the tool in order to include the 32-bit GAC. While that may be possible and that approach may work, a little more thought convinced me it wasn't the right approach to take here. The way I reasoned, if the tool has a dependency on a 32-bit reference, then the tool is not really architecture-independent after all! The problem is that the tool is claiming to be something it's not and that's what's causing it problems. If, when we compiled the tool, we were to specify the platform target of "x86" instead of "Any CPU" in Visual Studio (or using the /platform C# compiler option), then the tool should run successfully because it would naturally probe the 32-bit GAC where vjslib.dll lives.

And, indeed, that simple change fixes the tool, solves the problem, and answers the question of how something can be both IN and NOT IN the GAC at the same time! This investigation was a neat learning experience for me - I hope it's as much fun to read about as it was to experience! :)

Tags: Technical

When the GAC makes you gack (Part 1) [How something can be both IN and NOT IN the GAC at the same time]

I recently had occasion to use a particular tool for the first time and found that it didn't work on my machine. This was weird, because nobody else seemed to have any problems running the same tool on their machines. So I set out to determine what was wrong...

Simplifying things ridiculously for the purposes of this example, I'll note that the tool manipulates ZIP files, has a reference to "vjslib", and is compiled from code that looks something like this:

using java.util.zip;

class Program
{
    static void Main(string[] args)
    {
        new ZipFile("file.zip");
    }
}

(Aside: In case you're wondering what's up with the "java.util.zip" namespace and the reference to "vjslib.dll", I'll suggest that the author of this tool was probably following the recommendations of the article "Using the Zip Classes in the J# Class Libraries to Compress Files and Data with C#" which recommends exactly this approach. You may be aware that .NET 2.0 offers support for compressed streams via the classes in the new System.IO.Compression namespace. However, support for compressed streams is not the same thing as supporting the ZIP file format, so I believe this technique is still relevant.)

When run on my machine, the tool produces the following output (inadvertent profanity due to default 80-column wrapping of "assembly" removed for your protection):

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or as*
embly 'vjslib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
' or one of its dependencies. The system cannot find the file specified.
File name: 'vjslib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d
50a3a'
   at Program.Main(String[] args)

That's odd, because my computer DOES have the Microsoft Visual J# Version 2.0 Redistributable Package installed as required (it comes with a Visual Studio Team Suite full install). But it's worth checking the GAC (Global Assembly Cache) anyway, just to be sure that vjslib is present there as we expect:

C:\Program Files\Microsoft.NET\SDK\v2.0 64bit>gacutil -l vjslib
Microsoft (R) .NET Global Assembly Cache Utility.  Version 2.0.50727.42
Copyright (c) Microsoft Corporation.  All rights reserved.

The Global Assembly Cache contains the following assemblies:
  vjslib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, pro
cessorArchitecture=x86

Number of items = 1

Yup, it's in there. So why can't it be found by the tool? To try to answer that question, we turn to the Assembly Binding Log Viewer (Fuslogvw.exe). Just run the viewer, enable the "Log bind failures to disk" setting, run the tool again, then refresh the viewer and open the failed binding entry to see the following (abbreviated) output:

*** Assembly Binder Log Entry  (2006-03-23 @ 10:52:44 AM) ***

The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.

...

LOG: Post-policy reference: vjslib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
LOG: GAC Lookup was unsuccessful.
...
LOG: All probing URLs attempted and failed.

Hum, that's really odd... We know vjslib is in the GAC, yet it can't be found in the GAC. My machine is correctly configured, has the necessary components installed, and appears to be working fine in every other respect.

So what's going on here??

(Stay tuned for the exciting answer in Part 2!)

Tags: Technical

Working hard / hardly working [A bit about my new team]

My new team (affectionately known as the Agility Team (not to be confused with the A-Team)) is small and new and kind of different from the typical Microsoft team. I've been asked what it's all about, but haven't really had a clear, concise answer until now. My new manager, Shawn Burke, just wrote a post in which he outlines the nature and purpose of the team. He even gives a brief description of our current project which, if you've been paying close attention, was hinted at by Scott Guthrie in a recent post about Atlas. Like Shawn says in his post, this project is pretty cool stuff and I'm really looking forward to seeing what customers do with it once they get their hands on it. "I love it when a plan comes together!"

An image is now worth two thousand HTML tags [How to: Use ASP.NET's IHttpHandler interface to display a custom image]

In a previous post, I referred to some MSDN sample code and outlined the process of creating an ASP.NET page to display an image instead of HTML. As is often the case, the relevant sample code was written to demonstrate a concept rather than to be "production-ready". In one of the comments for that post, Heath Stewart suggested the use of a .ashx file as a more efficient way to do the same thing. This seems like a great opportunity to learn a little more about ASP.NET, so let's give it a try!

First, a little research is in order - I recommend starting with the documentation for Creating HttpHandlers and following up by learning a little about the corresponding IHttpHandler Interface. Armed with that knowledge, we should be able to convert the modified sample code over to the IHttpHandler interface.

Begin by creating a new file in the web site directory you were already using. I used Visual Studio's "Add New Item" action to add a "Generic Handler" page that was automatically named Handler.ashx. I then pasted in the existing code from my earlier post, tweaked a few minor things, and had a working IHttpHandler in considerably less time than it's taken me to write this post. :)

Here's what I ended up with in my Handler.ashx:

<%@ WebHandler Language="C#" Class="Handler" %>

using System.Drawing;
using System.Drawing.Imaging;
using System.Web;

public class Handler : IHttpHandler
{

    public void ProcessRequest(HttpContext context)
    {
        // Set the page's content type to JPEG files
        context.Response.ContentType = "image/jpeg";

        // Create integer variables.
        int height = 100;
        int width = 200;

        // ...

        // Create a bitmap and use it to create a
        // Graphics object.
        using (Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb))
        {
            using (Graphics g = Graphics.FromImage(bmp))
            {

                // ...

                g.Clear(Color.LightGray);

                // ...

            }

            // Save the bitmap to the response stream and
            // convert it to JPEG format.
            bmp.Save(context.Response.OutputStream, ImageFormat.Jpeg);
        }
    }

    public bool IsReusable
    {
        get
        {
            return true;
        }
    }
}

As you can see, the code is almost identical to the initial Page-based implementation! The only thing I think is worth calling out is that I've chosen to return "true" for the IsReusable property. The documentation for the IHttpHandler.IsReusable Property suggests that this property can be used to prevent concurrent use of the instance. Since our simple implementation doesn't make use of any global state, it should be safely reentrant, and therefore returns "true" to help ASP.NET avoid creating unnecessary instances of the class.

There you have it: a simple change that gives us an implementation consuming fewer resources and consequently scaling better on a busy web server. Thanks for the great suggestion, Heath!!

Tags: Technical

Start using using today! [A bit about the IDisposable interface and the using statement]

There's plenty to say about the IDisposable interface and the using statement, but you probably don't have time to read it all (and I don't have time to write it all!), so I'm going to try to keep this short and simple.

First, let's make sure we're all on the same page. If you're not familiar with the relevant concepts, please take a moment to learn about .NET Garbage Collection, the IDisposable interface, the using statement, and the use of objects that implement IDisposable. (If you're a bibliophile, I understand that the book "Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries" (ISBN 0321246756) contains additional material in section 10.3, "Dispose Pattern".)

Now that we're all familiar with the concepts, I'd like to call attention to a few things:

  • Implementation of the IDisposable interface by the author of a class is optional and completely unnecessary for a correctly written class. Even without IDisposable, the Garbage Collector will eventually clean up all of the class's resources (possibly with the help of a Finalize method override).
  • However, without IDisposable, there is no way of controlling *when* a class's resources will be cleaned up. The Garbage Collector (GC) runs only when it needs to, so it could be seconds, minutes, or even hours after you're done using a class before the GC runs and cleans up those resources. Any resources held by that class (like file handles, sockets, SQL connections, etc.) will remain in use until that class is cleaned up by the GC. This can cause unexpected problems when, for example, the user has closed a file in an application, but the application continues holding on to that file and prevents the user from copying it, moving it, etc.. Worse still, such problems will occur "randomly" according to whether or not the GC has run.
  • So it's a good practice to call IDisposable.Dispose whenever you're done using a class that implements IDisposable so that its resources can be freed immediately and deterministically (i.e., predictably). As a side effect, this helps minimize the resource consumption of your application which always makes users happy.
  • However, simply adding a call to Dispose at the end of a block of code isn't a complete solution because it means that Dispose won't get called if an Exception is thrown anywhere within that block of code. If you're going to call Dispose, you want to *always* call Dispose, so you really want the call to Dispose to be within the finally block of a try-finally statement pair.
  • To address this, you can manually add a try-finally pair, *or* you can use the using statement which does so for you! Under the covers, the using statement maps to a try-finally pair which calls Dispose for the specified object within the finally block, but the beauty of the using statement is that it's a simpler, more concise way of doing so that keeps all the relevant code in one place and hides the gory details from view. You can even declare and initialize the object in the using statement itself! (See the documentation for using for examples.)

With these points in mind, I propose following guidelines whenever dealing with an object that implements the IDisposable interface:

  • Always call the object's Dispose() method
  • Call Dispose() under all conditions (i.e., within a finally block)
  • Call Dispose() as soon as you're done with the object

Conveniently, the using statement makes it easy to do *all* of these things! The using statement is a simple programming construct that's very readable and that helps your code perform reliably, predictably, and efficiently. It doesn't get much better than that, so if you aren't already, please start using using today!

Tags: Technical

An image is worth a thousand HTML tags [How to: Display a custom image with an ASP.NET web page]

Imagine that you want to generate a custom image for your web site and that the content of the image will be dynamic enough that it's not possible to create the images beforehand. (One example might be an image of a clock displaying the current time.) It sure would be nice if you were able to create that image from an ASP.NET .aspx page whenever it was needed. But .aspx pages have to return HTML code, don't they? As it happens, they don't! While that's the job they perform most of the time, they can actually return any arbitrary data you'd like.

In this case, we want figure out how to return an image. Like many things in life, it's pretty easy once you know where to look. Specifically, the MSDN documentation for the HttpResponse.OutputStream property is a great place to start. The example on that page shows how to generate a custom JPEG image and return it from an ASP.NET .aspx page. Click the "Copy Code" link, create a new ASP.NET web site in your favorite editor, replace the contents of Default.aspx with the sample code, and view it in your favorite browser. Problem solved! (Well, close enough - customizing that image is left as an exercise to the reader. :) )

Digging a little deeper, we see that the sample code looks something like this:

private void Page_Load(object sender, EventArgs e)
{
    // Set the page's content type to JPEG files
    // and clear all response headers.
    Response.ContentType = "image/jpeg";
    Response.Clear();

    // Buffer response so that page is sent
    // after processing is complete.
    Response.BufferOutput = true;

    // ...
 
    // Create integer variables.
    int height = 100;
    int width = 200;

    // ...

    // Create a bitmap and use it to create a
    // Graphics object.
    Bitmap bmp = new Bitmap(
        width, height, PixelFormat.Format24bppRgb);
    Graphics g = Graphics.FromImage(bmp);

    // ...

    g.Clear(Color.LightGray);
    
    // ...
    
    // Save the bitmap to the response stream and
    // convert it to JPEG format.
    bmp.Save(Response.OutputStream, ImageFormat.Jpeg);

    // Release memory used by the Graphics object
    // and the bitmap.
    g.Dispose();
    bmp.Dispose();

    // Send the output to the client.
    Response.Flush();
}

Were I to use this code in a web page, I might change it to look a little more like this:

private void Page_Load(object sender, EventArgs e)
{
    // Set the page's content type to JPEG files
    // and clear all response headers.
    Response.ContentType = "image/jpeg";
    Response.Clear();

    // ...
 
    // Create integer variables.
    int height = 100;
    int width = 200;

    // ...

    // Create a bitmap and use it to create a
    // Graphics object.
    using (Bitmap bmp = new Bitmap(
        width, height, PixelFormat.Format24bppRgb))
    {
        using (Graphics g = Graphics.FromImage(bmp))
        {

            // ...

            g.Clear(Color.LightGray);

            // ...

        }

        // Save the bitmap to the response stream and
        // convert it to JPEG format.
        bmp.Save(Response.OutputStream, ImageFormat.Jpeg);
    }
}

Why? Well, I made three basic changes that I believe improve upon the original sample:

  1. I removed the use of HttpResponse.BufferOutput and HttpResponse.Flush. There seems to me to be no need to restrict the flow of data to the client in this case (on the contrary, let's allow it to start rendering the image as soon as possible). Unnecessary code is bad code, so it's gone.
  2. I converted the sample to take advantage of the using statement. You can read more about using in MSDN or wait for my next post in which I'll cover this handy statement in more detail.
  3. I dispose of the Graphics object as soon as it's no longer needed. Again, I'll cover the reasons for this in more detail in my post about the using statement.

So there you have it: Custom image generation with ASP.NET. It's easy to do and it leverages all your existing knowledge about graphics under .NET!

Tags: Technical

ASP.Newbie [Learning ASP.NET for fun and profit]

My new group at Microsoft has me learning ASP.NET. While I'm no stranger to .NET (having coded in C# for a few years now), ASP.NET hasn't been something I've used before now. Sure, I've had a few ideas about simple web pages that seem like they could be handy, but I've never had the time (or web server) to play around with ASP.NET. Well, it looks like my time has come...

The good news is that it's easier than ever to get started with ASP.NET. Start by downloading Visual Web Developer Express, a professional-grade development environment that's free for a year! (It even comes with a small, development-friendly web server that will save you from having to install IIS - nice touch!) Then surf on over to http://asp.net/ where you'll find a wealth of information about ASP.NET. Pay particular attention to the Tutorials which provide a great overview of ASP.NET. And while you're there, maybe you'll want to check out the technology preview of Atlas, an ASP.NET extension that's going to make AJAX applications simple to develop.

Lots of good stuff. No money down. What are you waiting for??

Tags: Technical