Common Knowledge

Semiconscious ruminations on the art and craft of jamming little bits of code down the gullets of various infernal machines.

Sunday, January 11, 2009

AJAX and the Pony Express

I sometimes teach classes at AcademyX, and by luck the San Francisco campus of AcademyX is located within walking distance of my office on Market St.  On my way to class, I often pass a collection of commemorative placards that mark the site of the old western terminus of the Pony Express on Clay St. between Kearny and Montgomery.  Many people have heard of the Pony Express: a heroic enterprise in which mail pouches where carried over the Rocky Mountain West in a tightly scripted relay of horses and riders.  Deliveries could make it from Missouri to California in just 10 days, which a very good time for horse and rider.

Pony Express Placard on Clay St.One surprising fact about the Pony Express is that it lasted less than a year as a going concern.  But Pony Express couriers are still galloping through the American imagination; even today the Pony Express emblem is used by the U.S. Post office.

It was technology that killed the Pony Express: the service was discontinued shortly after completion of the transcontinental telegraph.  This is a familiar story to those of us who've been following digital technology for very long.  Ingenuity, planning, and perspiration won't make the grade if you're competing against a superior platform.  With just a flick of the wrist, a telegraph operator could beat a team of Pony Express riders and their carefully build infrastructure of relay stations.  This got me thinking: could it be that Asynchronous JavaScript And XML (a.k.a. AJAX) will face the same fate as the Pony Express?

The role of the transcontinental telegraph in this story will be played by Rich Internet Applications (RIAs).  RIAs have actually been around since before AJAX, but they have been slow to catch on compared to the wildfire acceptance of AJAX among web developers.  But there can be no doubt that RIAs are catching on.  Flex has clearly had blockbuster success recently, and both Silverlight and JavaFX are waiting in the wings.

Now that AJAX interfaces are common on the web, the limitations of this architecture are becoming clear.  It's common for AJAX pages to become unresponsive when something goes wrong with a script based postback.  Error handling is a problem; most browsers have JavaScript error reporting turned off by default because errors are so frequent.  Last year I was blown away and frankly shocked by Alan Holub's presentation about the security problems associated with AJAX.  Most importantly, from a developer's perspective, AJAX can be a lot of work.  Of course there are frameworks that make simple and common effects easy to achieve.  But frameworks require debugging and customization: ultimately there's no escape from the complexity of the architecture.

Ultimately the advantage of an RIA platform is simplicity.  An RIA application is what it is: a stateful, sandboxed, and media rich application that can be scripted to respond to user interaction.  In fact, we can drop the "scripting", RIAs run compiled code, just like a decent programming environment.  An AJAX web application only appears to be these things.  There is no simplicity, even in the simplest AJAX enabled page.

As a programmer, what would you rather do: spend a few hours in a single development environment putting together an application with data binding, full user interaction, and some neat animations, or spend several days making an AJAX-enabled web page behave as if it were an RIA?  If you chose the AJAX path, you might just be as heroic as the Pony Express rider of old, doing the impossible with stout ponies, wits, and willpower.  No doubt you'll have some adventures along the way.  When you get to town, you'll find me a the telegraph office.

Monday, November 10, 2008

Adaptive Connection Strings for Windows Forms Applications

As a developer working with small businesses, I do a lot of Windows Forms based development.  One of the great things about this platform is the ease of deployment.  A traditional installation program can be created in a matter of minutes.  Better yet, with one-click deployment it's easy to update a client's machine at a remote location with the touch of a button.

In a small-scale custom development context, it's very common that simple updates are urgently needed.  This could be because of an undiscovered bug, but more commonly it is the result of an unknown or poorly understood business rule that emerges at the worst possible moment.  For example, during invoicing it is discovered that no one told the developer about new discount rules.  In this scenario a simple fix at the code level is usually possible, and extensive acceptance testing is counterproductive.  This is where quick and easy deployment makes everyone's life easier.

But there is one fly in the deployment ointment: the database connection string for the production environment is always different than the development environment.  That means that the last step in any deployment is resetting the database connection string.  There are several problems with this, including:

  1. If you forget to change the connection or make a mistake in resetting the string, your already cranky client gets an immediate connection error after the deployment.
  2. There's no obvious automatic way to make sure you don't make a mistake when you reset the string.
  3. There's no way to test within the development environment to make sure you've got the production connection right.  If you develop this way, every build you deploy is in fact an untested build, because it can't run successfully in the development testing environment.

What we really need is an application feature that will manage the connection string for us, that will make sure the correct connection string is always used.  It must be possible to set up the connection configuration once, test it in all environments, and then leave it alone.  This would allow us to deploy our changes without any changes to the connection string.  The feature should be valid for both application assemblies and DLLs that are deployed as components.  I call this feature, "Adaptive Connection Strings" and the rest of this post describes how to make it happen.

Getting Control of the Connection String

Almost all useful business applications have at least one database connection.  Whether you're using hand-coded ADO.NET Connection objects, table adapters, LINQ to SQL, or the ADO.NET Entity Framework to connect to your database, the most convenient and flexible option for managing database connection strings is to create connection string setting in the application settings class.  Visual Studio designers do this for you when you choose the save this connection option. But application settings of type connection string are always application level read-only properties, so it is not possible to build run-time logic to modify them.

But are connection string properties really read only?  Let's take a quick look at a connection string property definition in the Settings.Designer.cs class:

public string MyAppConnectionString {
    get {
        return ((string)(this["MyAppConnectionString"]));
    }
}

You can see that the property is clearly defined as read only.  But you can also see that the connection string property is really just an alias for a call to a indexer defined by the settings class.  The indexer used here is defined in System.Configuration.ApplicationSettingsBase to provide a reference to the Properties member collection.  It turns out that all application settings are accessible in read/write mode by using this indexer directly.  The following code demonstrates how to modify the connection string using this approach:

//change the application connection string
Properties.Settings.Default["MyAppConnectionString"] = strCnString;

//debug:verify that this really did work
Console.WriteLine(Properties.Settings.Default.MyAppConnectionString);

So we can set up the connection string at run time, as long as we have an effective place to put this code.  For example, we could put this in the constructor of the main form of an application.  But how do we determine which connection string to use?

Finding the Right Connection

The whole point of this technique is to make the connection adaptive; we want the application database connection to automatically adapt based on the context in which it is running.  This can be done in a number of different ways, but in most cases you will find the Environment class very helpful.  The static instance of this class can be used to collect information about the host of the current process.  I usually use the MachineName property to identify development workstations.  The code looks something like this:

    string ServerName;
    string DatabaseName;

    switch (System.Environment.MachineName)
    {
        case "DEV1":
        case "DEV2":
            ServerName = @"DEV\SQL2008";
            DatabaseName = "Test";
            break;

        default:
            ServerName = @"CONTOSO\BIGBOY";
            DatabaseName = "Production";
            break;
    }

    System.Data.SqlClient.SqlConnectionStringBuilder bld
        = new System.Data.SqlClient.SqlConnectionStringBuilder();

    bld.DataSource = ServerName;
    bld.InitialCatalog = DatabaseName;
    bld.IntegratedSecurity = true;

    Properties.Settings.Default["MyAppConnectionString"] = bld.ConnectionString;

This approach works well in small scale settings when you can be sure that there won't be duplicate machine names in different domains.  For a more scalable approach, you can also parse the domain name from the UserDomainName property of the static Environment instance.

At this point we're in pretty good shape.  We have a way to control the connection string at runtime, and we have a programmatic method to determine which connection string to use.  But that still leaves one important issue: we don't have a standard way to include this code in our projects that will guarantee the connection will be initialized before any data components are constructed.  For example, if we are building a DLL that exposes multiple public methods, there is no single entry point at which we can perform the initialization.  Wouldn't it be nice if we could simply handle a "load" event for the assembly settings?  It turns out that we can do that, and use the same technique whether we are building a stand-alone application or component.

Hooking Settings Initialization

In order to hook the load event for your assembly settings, you must first create a code behind file for the settings class.  To do this, select <app name> properties from the Project menu in Visual Studio, then click the settings tab.  This is the same screen that is used to modify connection string properties:

The project settings screen

Note the View Code button, which is highlighted by the red circle.  When this button is clicked, Visual Studio creates a Settings.cs file in the main directory of your application (you would expect this file to appear in the Properties directory, but it goes into the main directory instead).

When this file is created, it contains two pre-wired events: SettingChanging and SettingsSaving.  These events are of no use for our purposes.  In order to hook the SettingsLoaded event, you must manually add an event handler, as shown below:

public Settings() {
    //
    // To add event handlers for saving and changing settings,
    // uncomment the lines below:
    //
    // this.SettingChanging += this.SettingChangingEventHandler;
    //
    // this.SettingsSaving += this.SettingsSavingEventHandler;
    //

    this.SettingsLoaded +=
      new System.Configuration.SettingsLoadedEventHandler(Settings_SettingsLoaded);

}

void Settings_SettingsLoaded(object sender,
                              System.Configuration.SettingsLoadedEventArgs e)
{
    // Connection string initialization goes here
    // ...
}

You can now move the connection string setting code into the SettingsLoaded event.  Since you are in the code behind file for the settings class, you can replace references to Properties.Settings.Default with the this keyword:

this["MyAppConnectionString"] = bld.ConnectionString;

The connection string initialization is a good candidate for a code snippet.  In most cases the only difference in this code from project to project will be the server and database settings.

It should be noted that if you're using SQL Server Authentication or another connection type that requires a user name and password, you won't want to hook the SettingsLoaded event.  In this case, you'll have to display a login dialog to retrieve the authentication information.  But you'll still be able to use the technique described above to control the connection string properties of your application.

Conclusion

This post demonstrates a technique for adaptive connections strings that can be used for all Windows Forms application and component projects.  I've used this technique at my company, PJPM, to deploy patches and updates to clients very quickly and easily.  It definitely takes an important pain point out of the deployment process.

Followers

This is my blog!

My Photo
Paul Keister
Paul has spent over 14 years as a programmer, mostly in the Windows world, from Borland C++ all the way to WCF.
View my complete profile