# Sunday, January 20, 2008

I needed to get directions to a friends house today and sure enough I found myself using Google Maps to get directions.  Nothing astounding about that.  What did astonish, and delight me, was the fact that I found you can change your route just my dragging and dropping the route line displayed on the map!  Is this thing really a web application running on just HTML and JavaScript?

Even more amazing is that you can create hyperlink to send out to people using your new preferred route just by clicking "Link to this page."  I assumed it would lose my customized route, but it doesn't, it keeps it in the URL by specifying a direction change at an intersection.

From now on when sending directions or even my address I'm going to make sure to send it as a hyperlink to Google Maps.  It just makes sense.

Sunday, January 20, 2008 7:21:33 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, January 17, 2008

Setting up Monorail to work on IIS7 isn't necessarily straight forward.  First you need to configure IIS7 to handle the particular file extension you are using for Monorail.  This is just like you would do in IIS6, but with some slightly different menus and terminology.

I'm using .rails for this particular application.  For the website or virtual directory you are configuring in IIS7, open the Handler Mappings in IIS Manager.

HandlerMappings

From there create a new Script Map, by clicking "Add Script Map..."  This opens the Script Map dialog.  You should enter *.rails as the request path and the aspnet_isapi.dll path as the executable.

EditScriptMap

Once that is done, click "Request Restrictions" and then uncheck "Invoke Handler only if request is mapped to".

RequestRestrictions

Once that is done you may run into a problem with your monorail section in the web.config.  I had this error:

An error occurred creating the configuration section handler for monoRail: Object reference not set to an instance of an object.

 

Odd, my web.config works in IIS6 and in webdev.webserver.exe.  As it turned out I had to fill out the assembly element in my MonoRail section even though I'm using Windsor integration.  I've bolded the part I had to add below:

 

<monorail useWindsorIntegration="true">
  <controllers>
    <assembly>Sneal.Store.Commerce</assembly>
  </controllers>
  <viewEngines viewPathRoot="Views">
    <add type="Castle.MonoRail.Framework.Views.NVelocity.NVelocityViewEngine, Castle.MonoRail.Framework.Views.NVelocity" />
  </viewEngines>
</monorail>
Thursday, January 17, 2008 3:44:58 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [1]  | 

We all know that since Internet Explorer is integrated into the OS that you can't have two different versions of IE on one PC.  I have Vista on all my PCs, and there's no way to run IE6 on Vista.  What is a developer to do?  We could create Virtual PC running Windows XP with IE6, but why bother when the IE team has already created a freely downloadable IE6 Virtual PC image for you?  This is a lot easier and faster then going through the Windows setup wizard.

They have an IE7 image too.

Thursday, January 17, 2008 2:31:02 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, January 14, 2008

The footer now appears at the bottom of the blog in IE (IE 7 anyway).

The content area is floating so that the blog now takes full advantage of your wide screen monitor.  It certainly makes this blog a lot easier to read in 1600x1050.

Monday, January 14, 2008 7:45:02 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 

I posted last week about testing JavaScript through NUnit with JSUnit.  While this worked, it was a little slower to run tests than I really wanted.  It was also slower (for me) to write the tests since I had to leave the comfort of NUnit and .NET for JSUnit and JavaScript.

I'm continuing to look at the problem of JS testing for ASP.NET.  I evaluated YUI Test, Yahoo's JS unit test library.   YUI Test actually looks very good, but I really wanted to keep things integrated with my current build and test process, even if it isn't the best solution; you don't know unless you try.  ;-)

This time I'm only using NUnit and WatiN for my JavaScript tests.  Since WatiN now has the ability to evaluate JavaScript and return the results, I'm using this to run the JavaScript function under test and then using an NUnit assertion for validation.

I create each test using regular NUnit syntax, and then wrap the JavaScript function call with a C# method which passes the arguments off to the JS function to test.

[Test]
public void ShouldValidateDiscover()
{
    Assert.IsTrue(ValidateCreditCard("6011648040903965", "discover"));
}
 
private bool ValidateCreditCard(string cc, string ccType)
{
    string testJs = string.Format("var cc = new CreditCardValidator(); cc.isValidCreditCardNumber('{0}', '{1}');", cc, ccType);
    return EvalToBool(testJs);
}

The EvalToBool method just calls the WatiN eval method which accepts JavaScript as a parameter, and then converts the JS string result to a .NET boolean.

protected bool EvalToBool(string js)
{
    string result = ie.Eval(js);
    return bool.Parse(result);
}

The overall process is:

  1. Create a dummy HTML page which includes the JavaScript source file I want to test.
  2. Kick off WatiN and navigate to the dynamically created HTML file.
  3. Pass the JavaScript function to be evaluated by WatiN.
  4. Assert the eval call results using NUnit.

The test setup is very simple, and it runs fast for this type of test.  On my PC it was taking 1.7 seconds to setup the test fixture, and then .2 seconds to run each test.  The nice thing is that the errors are generally obvious and easy to diagnose since they are native NUnit tests.  Its also nice to have multiple NUnit test entries in the runner instead of one monolithic JavaScript test function which encapsulated all my JS tests that run in JSUnit. 

The tests can get ugly if a JavaScript exception is thrown, in that case you get a generic COM exception returned from WatiN rather than a nice error message.  The is one area where a JSUnit or YUI test are naturally better at.

This makes me wonder if WatiN couldn't be extended to return better error information from JavaScript, and whether the use of a dynamic .NET language along with NUnit couldn't make for a nice testing experience.

Monday, January 14, 2008 6:44:21 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Sunday, January 13, 2008

I created a new utility called ConfigPoke for creating application configuration files from a template and one or more property files.  The property files allow you to create a set of property files in which each subsequent file overrides any settings in the previous.

The input property files are just plain text files with key value pairs, for example:

dbConnectionString        = server=localhost;database=Northwind;integrated security=SSPI
sessionConnectionString = server=localhost;database=AspState;integrated security=SSPI
smtpServer                  = localhost

 

This allow me to define a base set of shared developer properties and then I can define my own property file for me which overrides just properties, like the local database connection string.  I also define property files for each of my environments I deploy the application too: dev, test, release, live.

This utility integrates tightly with MSBuild and Visual Studio 2005/2008 using it's own target file.  There is also a command line interface for the application that can be used from NAnt or in your deployment process (NSIS in my case).

Per developer configuration happens automatically and is always up to date with the input template and property files with Visual Studio integration.  The output configuration files are conditionally built only if the input templates file or input property(s) files are changed, just like any regular source file in Visual Studio. If a Rebuild action is initiated in Visual Studio, the output configuration files are always rebuilt, even if the input files have not changed.

 

I've been using this utility for the past week at work, and it has worked really well.  Edit a property and everything just works.  Machine specific settings have proven invaluable especially on my laptop which has a lot of non-standard settings because I usually work disconnected on it.

 

You can download the MSBuild target DLL, console EXE, and MSBuild targets file from Google Code.  The code and the binary is release under the Apache 2.0 license.

Visual Studio 2005/2008 Integration Outline

  1. Import Sneal.Build.ConfigPoke.targets file into your VS project file.
  2. Create a ConfigTemplateFiles ItemGroup.
  3. Create a ConfigPropertyFiles ItemGroup.

Detailed Visual Studio 2005/2008 Integration Instructions

Include the Sneal.Build.ConfigPoke.targets file in your Visual Studio project file (csproj) using the following element:

<Import Project="Sneal.Build.ConfigPoke.targets" />

With the ConfigPoke MSBuild targets file included, the configuration building will automatically be hooked into the Visual Studio clean, build, rebuild process.

The Sneal.Build.ConfigPoke.targets file requires two MSBuild item groups as input: ConfigTemplateFiles?, and ConfigPropertyFiles?. These must be specified in your MSBuild (csproj) project file. Each ConfigTemplateFiles? item should be the destination filename + some arbitrary extension, I use '.template'. You may also probably want to set the "InProject?" item meta data to false so these templates or property files don't show up in VS solution explorer.

Here's an example ConfigTemplateFiles? ItemGroup? that you would put into your csproj file:

<ItemGroup>
  <ConfigTemplateFiles Include="$(MSBuildProjectDirectory)\Configs\web.config.template"/>
  <ConfigTemplateFiles Include="$(MSBuildProjectDirectory)\Configs\windsor.config.template" />
</ItemGroup>

To create user and machine specific overrides, you can include a base properties file and then optionally include a per user and per machine config, if they exist. This would allow each developer to create their own override properties file which can then be optionally checked into source control. To automatically set this up, you can take advantage of the built in MSBuild properties: USERNAME and COMPUTERNAME.

Here's an example ConfigPropertyFiles? ItemGroup? that you would put into your csproj file:

<ItemGroup>
  <ConfigPropertyFiles Include="$(MSBuildProjectDirectory)\Properties\App.Properties.base"/>
  <ConfigPropertyFiles Include="$(MSBuildProjectDirectory)\Properties\App.Properties.$(USERNAME)" Condition="Exists('$(MSBuildProjectDirectory)\Properties\App.Properties.$(USERNAME)')"/>
  <ConfigPropertyFiles Include="$(MSBuildProjectDirectory)\Properties\App.Properties.$(COMPUTERNAME)" Condition="Exists('$(MSBuildProjectDirectory)\Properties\App.Properties.$(COMPUTERNAME)')"/> 
</ItemGroup>

Note: You cannot pass in non-existant property files to the ConfigPoke utility, hence the Condition check above.

 

Optionally you can specify a ConfigPokeDirectory? and a ConfigOutputDirectory? property to override the default directories. The ConfigPokeDirectory? property should point to the directory where Sneal.Build.ConfigPoke.MSBuild.dll is located on your machine, if not specified this property will default to the current MSBuild project file directory. The ConfigOutputDirectory? property should point to the directory where the output configuration files are written too. If not specified this property will default to the current MSBuild project file directory.

 

For additional usage see the example in SVN, http://sneal.googlecode.com/svn/trunk/ConfigPoke/Sneal.Build.ConfigPoke.Example/Sneal.Build.ConfigPoke.Example.csproj

Sunday, January 13, 2008 1:39:35 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Saturday, January 12, 2008

I like to re-use code between projects, whether for personal use or professionally, so I created an Apache 2.0 licensed code repository.  Right now I just have my application configuration build tools committed (which I'll post about later).

The project home page is: http://code.google.com/p/sneal/

The project SVN URL is: http://sneal.googlecode.com/svn/trunk/

Saturday, January 12, 2008 8:01:44 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, January 10, 2008

The company I work for, GalleryPlayer in downtown Seattle (Pioneer square), is looking for a couple of software engineers to develop our next generation content distribution system.  I've worked for GP since last May and I really enjoy the work and the people

Why would anyone want to work for our small startup?

  • As an engineer you'll have a lot of influence over technology and design.
  • We prescribe to the Programmer Bill or Rights.  No you won't have your own office.
  • Our dev environment consists of: SVN, CC.NET, VS 2005, Re#, SQL Server 2000, NUnit.
  • Good location, Pioneer Square in downtown Seattle.  5 minute walk from the Sounder commuter rail station and bus lines.
  • Casual work environment - wear whatever makes you comfortable.
  • All the free, fresh, Starbuck's you can drink... and a toaster.  Yes, we trust you with a toaster!
  • We're using Castle Windsor, MonoRail, and Prototype for our web development backed by unit tests (and perhaps ASP.NET MVC when MS releases a Go Live license).
Thursday, January 10, 2008 9:03:38 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 

I consolidated a few duplicate categories and removed some others that just had one post under them to make the site a little more usable.  Next I'm going to work on the look and feel of this blog and make it work better in IE.

Thursday, January 10, 2008 8:30:23 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 

Developed data access class containing over 5,000 lines of code and over 100 methods

WTF
Thursday, January 10, 2008 8:28:45 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, January 09, 2008

We've all written a few console apps in our time, but how often do we spend anytime creating a help command line switch that spits out how to use the app?  Hopefully you answered, "everytime."  There's nothing more annoying than a console app that doesn't display a man page if you forget to supply required parameters.

It's so easy to add syntax help, especially if you drop the Console.WriteLines in favor of an embedded text file resource.  This way you can edit your command line usage as plain text which is so much easier to write and maintain.  This may seem obvious, but often time we forget because, "it's just a quickie console app."  So the next time your find yourself writing a console utility, remember to use an embedded text resource as your help (or man) page.

EmbeddedResource

Other than actually creating the text file and marking it as an embedded resource, this all the code required (don't forget to prefix your text file with the default assembly namespace):

private static void Usage()
{
    using (
        Stream s =
            Assembly.GetExecutingAssembly().GetManifestResourceStream(
                "Sneal.Build.ConfigPoke.Console.usage.txt"))
    {
        using (StreamReader reader = new StreamReader(s))
        {
            System.Console.WriteLine(reader.ReadToEnd());
        }
    }
}
Wednesday, January 09, 2008 6:51:36 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, January 07, 2008

I have no proof of this other than my changes weren't showing up, but it seems like MSBuild project files that are directly imported into a project are cached in Visual Studio between builds.  I had to make changes to my imported build script, exit Visual Studio, then restart VS before my changes would take affect.  Luckily if you build from the command line this doesn't happen.

Monday, January 07, 2008 8:45:28 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 

I often need to refer to tools and libraries in my SVN repository that live in a folder not underneath the current project folder.  For instance I may need to use NUnit from trunk\store\web, but NUnit lives under trunk\tools\nunit\bin. 

Relative to the trunk, I know where to find NUnit, but where's the trunk?  The trunk may be checked out to c:\source\mytrunk or e:\work, or even the user's documents and settings folder.  This means I must use relative paths to NUnit from the current project directory, but this gets tricky if I have an external MSBuild target file that is shared between projects.

The only way to tell the shared imported targets file where things are relative to it, is to have the parent MSBuild script to pass in a property telling it where the root of the source control folder is (or where the tools directory is).  In my case this is the 'SourceDirectory' property which should point to the root of my source control folder hierarchy.  This gets annoying after a while since everywhere I include the shared targets file I first must create the SourceDirectory property first, like so:

<PropertyGroup>
  <SourceDirectory>$(MSBuildProjectDirectory)\..\..</SourceDirectory>
</PropertyGroup>

 

Yes this works pretty well, but it makes the shared imported targets file not-so-self contained and I have to repeat this over and over again in every project file that wants to include the shared targets files, which in my case is every single csproj file.  I have to do this since my project files live at varying depths in the folder hierarchy.  Instead of specifying this property everywhere, I've put this at the top of my shared targets file:

<PropertyGroup Condition="'$(SourceDirectory)' == ''">
  <SourceDirectory Condition="'$(SourceDirectory)' == '' And Exists('$(MSBuildProjectDirectory)\Master.proj')">$(MSBuildProjectDirectory)</SourceDirectory>
  <SourceDirectory Condition="'$(SourceDirectory)' == '' And Exists('$(MSBuildProjectDirectory)\..\Master.proj')">$(MSBuildProjectDirectory)\..</SourceDirectory>
  <SourceDirectory Condition="'$(SourceDirectory)' == '' And Exists('$(MSBuildProjectDirectory)\..\..\Master.proj')">$(MSBuildProjectDirectory)\..\..</SourceDirectory>
  <SourceDirectory Condition="'$(SourceDirectory)' == '' And Exists('$(MSBuildProjectDirectory)\..\..\..\Master.proj')">$(MSBuildProjectDirectory)\..\..\..</SourceDirectory>
  <SourceDirectory Condition="'$(SourceDirectory)' == '' And Exists('$(MSBuildProjectDirectory)\..\..\..\..\Master.proj')">$(MSBuildProjectDirectory)\..\..\..\..</SourceDirectory>
  <SourceDirectory Condition="'$(SourceDirectory)' == '' And Exists('$(MSBuildProjectDirectory)\..\..\..\..\..\Master.proj')">$(MSBuildProjectDirectory)\..\..\..\..\..</SourceDirectory>
  <SourceDirectory Condition="'$(SourceDirectory)' == '' And Exists('$(MSBuildProjectDirectory)\..\..\..\..\..\..\Master.proj')">$(MSBuildProjectDirectory)\..\..\..\..\..\..</SourceDirectory>
  <SourceDirectory Condition="'$(SourceDirectory)' == '' And Exists('$(MSBuildProjectDirectory)\..\..\..\..\..\..\..\Master.proj')">$(MSBuildProjectDirectory)\..\..\..\..\..\..\..</SourceDirectory>
  <SourceDirectory Condition="'$(SourceDirectory)' == '' And Exists('$(MSBuildProjectDirectory)\..\..\..\..\..\..\..\..\Master.proj')">$(MSBuildProjectDirectory)\..\..\..\..\..\..\..\..</SourceDirectory>
</PropertyGroup>

 

What this does is look for a Master.proj file in each directory traversing upwards until it finds one, at which point the SourceDirectory property becomes set.  I can do this since I know that I only ever have one Master.proj file in the root of my SVN repository, and I never have a project more than 4 folders deep (although here I support 9 levels)  It's kind of cheesy, but it works well and saves me from having to do anything other than just import the shared targets file.

<Import Project="$(MSBuildProjectDirectory)\..\..\utils\gp.vs.targets" />

 

Hopefully Microsoft will add a well known property that allows you to get the current directory of the current build file, rather than just the parent script directory like MSBuildProjectDirectory does now.

Monday, January 07, 2008 7:46:42 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  |