# Thursday, May 22, 2008

I've been using the Microsoft SDC tasks to deploy IIS websites, and for the most part this has worked well once I grabbed the latest source from CodePlex; I ran into a few bugs that have been fixed since the last release.

Anyways, I've run into an annoyance with regards to local development builds on Windows XP.  Most of our devs are still using XP for their development platform which as you may know uses an old version of IIS - IIS 5.1.

  • No app pools
  • Single site only
  • No SSL

So, what does this have to do with the SDC tasks?  Well, I want the MSBuild script to fail gracefully with an intelligent error message when run on Windows XP.  Something like:

This version of IIS is not supported, IIS 6.0+ is required.

I couldn't find a decent built-in supported way in MSBuild to get the IIS version, let alone the operating system version.  You would think this would be supported without resorting to C#, but I couldn't find a way.  So what I ended up doing was using the command line "ver" command and piping that to a text file and then reading it back in.  Here's what that looks like:

MSBuild_OSVer

Thursday, May 22, 2008 4:02:50 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [2]  | 
# Friday, May 16, 2008

I needed to create an xml fragment that had optional elements that was serialized from a class.  The optional elements were integers and decimals, types that are not nullable by default in .NET.  Well, we can wrap those types in Nullable<T> and then add an another ignored property that helps out the .NET serializer.

[XmlElement(Order = 10)]
public decimal? Height
{
    get { return height; }
    set { height = value; }
}

 

[XmlIgnore]
public bool HeightSpecified
{
    get { return height.HasValue; }
}

 

With the additional HeightSpecified property, the XmlSerializer will only write out the Height property element if its non-null.

 

Initially I tried using [XmlElement(IsNullable=false)] on the Height property, but that ended up throwing an InvalidOperationException when I went to serialize my class. 

Friday, May 16, 2008 5:55:11 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, April 28, 2008

I really like what Microsoft has done with the web development capabilities of Visual Studio 2008, they seem so much more mature and refined than in previous versions.

For instance, when you open up a new project in Visual Studio 2008 that has been configured to run under IIS, it now asks you if you would like VS to create the virtual directory for you in IIS.  No need to open up inetmgr and manually type in directory paths and virtual directory names.

Not only that, it creates the virtual directory in the correct place which is source control friendly, i.e. in place, not under some c:\inetpub\wwwroot folder like it used to do with Visual Studio 2003.  Microsoft finally figured out that .NET developers actually use source control.

Additionally you can now apply the settings on a per project basis, not on a per developer basis.  This is very handy when you want to share settings between devs, like when you have tests that are dependant upon web URLs.

VS2008WebSettings

Monday, April 28, 2008 4:29:14 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, April 25, 2008

In my spare time I've been working on a utility for generating SQL scripts and XML data documents.  The utility currently only supports SQL Server 2000/2005, but could easily support any other database that has an OLEDB provider via the MyMeta library.  The main goal of this tool was to produce scripts to be checked into source control, and to generate differential scripts between databases for use in db upgrades (migrations).

 

First and foremost, if you have a migration tool ala RoR ActiveRecord in your environment - use it.  A migrator written in a DSL is going to be much quicker to get going... and since you're working at a higher abstraction level it allows you to target many different databases with the same DSL code.  There are a few out there, so take a look.

 

My first goal was to get a baseline script of our databases.  There are quite a few tools out there for this, but I really wanted the ability to tweak the output of my scripts just so.  I really like scripts that don't error when you run them multiple times, so this generally requires an IF EXISTS before any action.  To get things formatted and written the way I wanted them, I ended up using NVelocity along with a few templates.

 

Secondly, I wanted to use XML to store my data.  I like XML files better than SQL scripts for several reasons:

  1. XML files are easier to edit than a SQL script with a bunch of insert statements.
  2. Its faster to bulk load XML data then run a bunch of SQL inserts (using SQLXmlBulkLoad).
  3. I can edit the XML data in a tabular fashion inside Visual Studio by switching to DataGrid view.
  4. Its easier to produce a diff between a table and an XML document than a SQL script and a table.
  5. XML is meant to transfer data between systems, so why not use it?

To load XML data into SQL Server I created a wrapper around the SQLXmlBulkLoad COM component.  It works good enough for what I need, however it does make some assumptions about the way things are structured, its not quite as general use as BulkXml

The one advantage my implementation has is that when you run the loader, it generates the XSD that the SQL Server bulk load component requires at runtime based off the target table, so there's no need for you to hand write an XSD or worry about checking it into source control.

Here's how you would use SqlMigration to transfer data from one db to another (assuming the target db table is empty):

This creates an XML file for all the data in the customer table on my local machine:
sneal.sqlmigration.console /dir=c:\mydb /xmldata /tables=Customer /server=localhost /db=AdventureWorks

This applies the XML file just generated to my prodsql1 SQL Server.
sneal.sqlmigration.console /server=prodsql1 /db=AdventureWorks /execute=c:\mydb\data\dbo.Customer.xml

Pretty straight forward.  I'm not sure I like the command line syntax since you could potentially run an execute and script command at the same time.  I'm thinking of creating a separate console application for loading data and running scripts, or at least providing a command line switch that sets the mode to either input or output only.

I would like an MSBuild target wrapped around this, but I haven't needed that yet.  Another thing lacking is the ability to point it at a database and say "script everything."  That feature I know I'm going to need here very shortly.  Hopefully I'll have some time to fix the DDL migration portion of the tool, right now only migration (diff) SQL data scripts are supported.

As always, the code can be checked out from Google code via SVN (VS 2005).  Eventually when the tool is a little more mature I'll post a binary.

Friday, April 25, 2008 2:39:16 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, April 07, 2008

It seems like we've all done this a hundred times before.  I know I have.  What I really want is a strongly typed argument object passed in from the command line, but all we get is a bunch of strings to parse through.  Yuck, I hate parsing strings.

There are a few existing command line parsing libraries in .NET.  I thought about using one of them, but I either ran into licensing issues, old .NET 1.1 code, or the library was just too big and over complicated for what I wanted.

Needing this functionality yet again, I decided to create a re-usable library that allows me to create my command line arguments via property attributes.  To create a new argument class I just apply a SwitchAttribute to each property I want settable from the command line.

    public class Options
    {
        private int port;
 
        [Switch("Port", "Sets the IP Address port of the server.")]
        public string Port
        {
            get { return port; }
            set { port = value; }
        }
    }

 

Then to use this options class from my console application, I only need to:

    private static int Main(string[] args)
    {
        CommandLineParser parser = new CommandLineParser(args);
        Options options = parser.BuildOptions(new Options());
 
        if (options.Port != 0)
        {
            // ...
        }
    }

 

As you can see, this is nothing fancy, but it makes building new console apps a little easier, and more importantly it makes adding or changing command line arguments much more maintainable since I only need to modify a single property forgoing any string parsing.  I can also get a nicely formatted list of what command line arguments are available along with their descriptions.

    foreach (string line in CommandLineParser.GetUsageLines(new Options()))
        System.Console.WriteLine(line);

 

Outputs:

/Port    Sets the IP sddress port of the server.
/Server   Sets the name of IP address of the server.
...

 

If you interested in using the library, its available in my Google code SVN repository under the Apache 2.0 license.

Monday, April 07, 2008 6:11:50 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, April 04, 2008

I was using ReSharper's Unit Test Runner today, and all was good until it suddenly stopped working with no error message.  You would run the tests, it would spin for a second, then show no results - everything was grey.  Try to run test in debug mode, same thing, no break points ever get hit.

This was very frustrating since I had no indication of what the problem was.  I ended up throwing the test DLL into NUnit itself, which showed a nice error dialog "Assembly Not Loaded" which indicated there was an error in the test project's app.config.  Argh!

At least it gave me an excuse to download and install NUnit 2.4.7.  Apparently they added rowtest support?  I like the sound of that.

WTF
Friday, April 04, 2008 10:42:55 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, March 20, 2008

You might immediately suspect a C# class is breaking the single responsibility principle when you discover upon opening it that the entire first page is nothing but using statements.  38 in all, and that's after using Re# to remove the unused ones.

Can you guess what kind of class this is?

If you guessed a code behind to a winform dialog then you guessed right.

.NET | WTF
Thursday, March 20, 2008 10:27:40 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Saturday, March 15, 2008

I haven't been doing a lot of blog posting or work on my own personal projects this past couple of weeks because I've been spending my time reading.  I read the majority of WCF Programming, and have almost finished Release It.

Programming WCF Services is pretty much what you would expect from a book with this kind of title.  Lots of code examples of WCF.  Pretty dry and boring, but still the book goes into more depth than a lot of books on the topic.  The plethora of code is also very handy as a reference guide.  Overall I would recommend the book if you intend on doing any in depth WCF programming.  I do wish the book would have covered how to build better services: service contracts, data contracts, faults.  I suppose those topics are more general than WCF. My rating: 4 out of 5 stars.

Release It!: Design and Deploy Production Ready Software is the best book I've read in a long time.  There's only a couple lines of code in the entire book, yet the book provides excellent insight into design and architecture decisions for building and running robust, scalable, enterprise software.  If there's one take-away from this book, its design your systems to be loosely coupled, don't let a failure in a downstream service or application force your application to fail - build your software to be cynical.

Use timeouts!  Make services asynchronous.  Pay special attention to external integration points: services, networks, databases. Apply circuit breakers at external integration points.  Manage your resources wisely: bandwidth, CPU, and RAM are only so cheap, especially for large enterprise applications in a large farm.  Pay attention to your software once it goes live, don't throw it over the wall to IT. 

Build in monitoring and logging from the beginning, this could mean the difference between 10 minutes of down time and a days worth of down time.  Make your logging messages clear, so that IT can understand them.  Your customer facing software is your company, if your software performs poorly or malfunctions, it reflects poorly on your company, which ultimately shows up as lost revenue.

Again, Release It is an excellent book.  Go get a copy!  My rating: 5 out of 5 stars.

Unfortunately I've read the entire book in less than a week, and here I am without a book to replace it with.  My company was nice enough to give me an Amazon gift certificate, just for doing my job, so I decided to stock up so I wouldn't be without a book again, for a little while anyway.  I just ordered what I would consider to be "the essentials", since they are so often referred to:

  • Patterns of Enterprise Application Architecture
  • Refactoring to Patterns
  • Test Driven Development: By Example
Saturday, March 15, 2008 5:16:57 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  |