Thursday, May 31, 2007

Numbers, numbers everywhere - fixing VS2005's Assembly Numbering Limitations

Assembly numbering isn't something that a developer will generally bother too much about - so long as your references are up to date and the code works, what does it matter if the AssemblyVersion or AssemblyFileVersion are permanently locked at 1.0.0.0? Unfortunately, with the complex interaction of class-libraries in large projects, we need to be a bit more deliberate about things.

The two properties in question, AssemblyVersion and AssemblyFileVersion, are controlled through assembly attributes in the AssemblyInfo.cs file for a class library. You can find this in the Properties folder of a project.

When you create a new Class Library project, these properties will be set as shown in the following snippet from AssemblyInfo.cs.

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:

[assembly: AssemblyVersion("1.0.0.*")]
[assembly: AssemblyFileVersion("1.0.0.*")]

Visual studio lets you "default" the Build and Revision numbers using an asterisk (*) in the property. HOWEVER, it ONLY works for the AssemblyVersion property, NOT the AssemblyFileVersion property. This means that whilst your AssemblyVersion can automatically increment, the AssemblyFileVersion cannot.

Fortunately, there's a workaround from Microsoft - an additional MSBuild task that can be added to a project file which causes the two properties to be updated on every build.

Of course there's a downside - setting this up for every project involves adding a line to the .csproj file directly. What follows is a walkthrough of the process.
  1. Install the AssemblyInfo task downloaded from the MSBuild Tasks website.
  2. Create a customised build target file according to the instructions.

    I created a copy in the installation directory, but you can put it wherever you want - just be sure to update the path in step 3 below.

    My customisation was configure the task so that the AssemblyFileVersion had fixed Major and Minor versions, but the Build number represented the day and month the build took place and the Revision number again autoincremented.

    The critical code from the targets file is this:


    <PropertyGroup>
    <AssemblyFileMajorVersion>1</AssemblyFileMajorVersion>
    <AssemblyFileMinorVersion>0</AssemblyFileMinorVersion>
    <AssemblyFileBuildNumber></AssemblyFileBuildNumber>
    <AssemblyFileRevision></AssemblyFileRevision>
    <AssemblyFileBuildNumberType>DateString</AssemblyFileBuildNumberType>
    <AssemblyFileBuildNumberFormat>00MMdd</AssemblyFileBuildNumberFormat>
    <AssemblyFileRevisionType>AutoIncrement</AssemblyFileRevisionType>
    <AssemblyFileRevisionFormat>00</AssemblyFileRevisionFormat>
    </PropertyGroup>


    You can, of course, configure the task to modify the AssemblyVersion in the same way.
  3. Add the following additional target import to each project file (*.csproj) just after the default Microsoft.CSharp.targets import.

    <Import Project="$(MSBuildExtensionsPath)\Microsoft\AssemblyInfoTask\Custom.VersionNumber.Targets"/>

    This is the magic that instructs the compiler to run the AssemblyVersion task each time the project is build.
It's a small chore to update each project, but the result is a much more useful format for the two properties.

[assembly: AssemblyVersion("1.0.0.03")]
[assembly: AssemblyFileVersion("1.0.000214.02")]

The AssemblyVersion build number auto-increments, and the FileVersion includes the build date where before it was just a static value.

There's one slight wrinkle with this method of your project is under source control, however. The AssemblyVersion task it relies on being able to write changes into the AssemblyInfo.cs files just prior to compilation - so if your source control package write-protects files until you check them out, the process will error.

For TFS users, this post on the MSBuild Team Blog gives additional build targets to add to your project file that will check-out the relevant files, and then check them back in again afterwards. It's targetted at automated builds, but is easy enough to modify.

But the simplest method is simple to ensure that AssemblyInfo.cs is checked out before you build by using a pre-build script in each project. The following script works perfectly for TFS-controlled projects (note the quotes, tho', and the use of a relative path for the AssemblyInfo.cs file).
"$(DevEnvDir)\tf.exe" checkout ..\..\Properties\AssemblyInfo.cs

Of course, this won't check in the changed files, but that's sometimes a benefit!

The AssemblyVersion MSBuild Task allows fine-grained control of assembly and file version numbers - when this method is linked with that of a ProductInfo.cs solution file (on which I'll blog later), you gain real control over the meta-data embedded into your products.

Friday, January 05, 2007

Wierd compilation error - corrupt lines in FileList.txt

I came across a very strange error last night that flumoxed my for a while.

Compiling a solution, three of the sub projects failed to compile with the following cryptic error:
Files had invalid value "S....."
It turns out that the cause and solution are both quite simple, but neither is obvious.

Firstly, what does "Files" mean in this context?

Well, when VS2005 compiles a project, it reads a file in the obj directory named .csproj.FileList.txt, creating it first if required. This file contains a list of the DLLs and PDBs that will be generated, as well as one named ResolveAssemblyReference.cache, which (I assume) is passed to the command-line compiler used to actually perform the compilation.


As for the "invalid value", this turned out to be a corrupt line in the file, nothing more, so the solution is just to delete the obj\.csproj.FileList.txt file completely, clean the project and rebuild. Job done.

Strangely the only reference I could find to the FileList.txt file was in this posting by Sayed Ibrahim Hashimi, confirming that this is one of those undocumented "features" of VS2005.

Tuesday, December 19, 2006

Debug viewer saves the day!

Not that you should be putting debug builds into a production environment, but when you do how do you view the debug output? You can’t run using the VS debugger so what do you do?

Well, I found this tool today, and it's the answer to your (and my) prayers!

http://www.microsoft.com/technet/sysinternals/utilities/DebugView.mspx

Naturally, it's a Sysinternals product (OK - they're owned Microsoft now) - go get it!


Monday, December 18, 2006

ASP.Net AJAX on an existing site (redux)

How-To's are almost always useful - and this one from Jay Kimble is no exception.

In it, he explains in detail How To: Enable Microsoft ASP.NET Ajax Extension RC1 (and Dec. 2006 CTP) on an existing site
- something I've blogged on before, but it's nice to have a second piece for reference.

Thursday, November 23, 2006

Roland Weigelt's GhostDoc - Just use it!

I've been trying this VS2005 add-in for the last couple of days, and it's safe to say that it ROCKS!

From the site:
GhostDoc is a free add-in for Visual Studio that automatically generates XML
documentation comments. Either by using existing documentation inherited
from base classes or implemented interfaces, or by deducing comments from
name and type of e.g. methods, properties or parameters.
In use, it's great for going back over hurriedly written code to write the in-code comments we're all SUPPOSED to write as we go - took me about a minute to completely document a complex ASP.Net server control, and I had to adjust the comments of only 3 methods.

Get Roland Weigelt's GhostDoc - you know it makes sense!

Wednesday, November 22, 2006

Quick Tip: Checking for a reference type null in C#

How do you test for a null reference type in C#?

You'd think that it'd be easy to check for a null, just use some code like this:

MyType thing = null;
...
if ( thing == null)
{
// do something
}

But what if you need to test for a null within an overloaded == operator?!
You can't use the simple code above, as this would cause a stack overflow.

The trick is in casting the entity to a different type and so that the compiler uses the == for that alternate type. I wrap this test into a static IsNull() method on the class.

public static bool IsNull(MyType thing)
{
object testThing = thing as object;

// uses the == operator from object, NOT MyType
return (testThing == null);
}

So now I can safely test for equality, including correctly testing for nulls like this

public static bool operator == (MyType thing1, MyType thing2)
{
// two nulls => equal
if (IsNull(thing1) && IsNull(thing2))
return true;

// one null => not equal
if (IsNull(thing1) || IsNull(thing2))
return false;

// do the REAL equality test here
...
}

Simple when you know how! And absolutely essential when you're implementing IEquatable.

Friday, November 17, 2006

Sometimes the simplest things are most effective

I've been playing with Joel Fjordén's Code Style Enforcer
recently, and reckon it's one of the smallest, simplest and most useful VS IDE plugins around.

It's basically a DXCore plugin that redlines (draws a hand-drawn red line underneath) any c# code that doesn't meet the basic style guidelines from the iDesign C# coding standard.

I have to admit that finding the right properties page for the plugin to let me customise the rules too a while (find it by selecting DevExpress -> Options -> Code Standard -> Name Rules from the VS menu), but now it's great - I get instant feedback when I'm not meeting the basic coding standards.

Find it here...
http://joel.fjorden.se/static.php?page=CodeStyleEnforcer
And go use it!

Tuesday, October 10, 2006

JSON - The bottom sponge in the cake

You can hardly have missed the explosion of "Web 2.0" sites, and the excitement around AJAX and in the .Net community, ATLAS.

However, when using the wonderfully simple UpdatePanel from ATLAS, it's actually the markup that's being sent over the wire as part of an asynchronous call.

It's been at the periphery of my consiousness for a while, but I came across a link to Jayrock today that makes me mindfull of optimising the out-of-band communications by using something a bit more clever than markup deltas.

Jayrock is a framework for JSON and JSON-RPC for .NET - it makes exposing services to JSON-RPC as easy as creating an HTTPHandler.

And it's open source too!

Strong names and Assembly loading

The MSDN Flash newsletter that hit my inbox today contained a number of interesting things, but what most piqued my interest was a link to a very good article on VSJ.

Titled Strength in naming, it provides a very good overview of how strong names are used to sign assemblies, which in turn allows them to be inserted into the GAC.

In it, Ian Stevenson provides a very nice little flow-chart of the assembly loading process - the article is worth a read just for that.

Thursday, September 28, 2006

Using Generic types in DataContracts

In a short post titled "DataContract names for Generic Types
", Sajay Antony provides a wonderfully useful snippet of code to allow you to use generics in your WCF data contracts. Short, sweet and useful.

Friday, September 22, 2006

Debugger bites man

In this blog entry, Anson Horton holds his hands up as being (at least partially) responsible for a feature of the VS debugger that is at once invaluable and incredibly frustrating - Function Evaluation.

He also describes the problem very clearly, which is an effective reminder about not writing code that can self-substantiate unless that is essential.

Of course, when you're writing complex OO architectures, self-substantiation is a real temptation - but with this clear reminder, it should be easier to spot those occasions when self-substantiating objects have masked the fault condition.

Required reading.

Saturday, September 16, 2006

Plip does it again!

Wednesday saw another well-organised, interesting and informative VBUG event - this one a "SPECIAL NON-MEMBER EVENT" entitled "Flirting with AJAX with Gary Rowntree".

The location was once again QA Training in Stockport - a great little venue apart from the very hard seats!

Gary did a great intro to ATLAS - Microsoft's AJAX technology libraries - easing those who'd not played with it before through the concepts and basic techniques whilst fielding deep technical questions from others in the audience. Finishing the session off by writing a simple chat application from scratch was a definite crowd pleaser.

It was nice to be able to chat to other developers and guage their experiences with the technology, and I think that the informality of these events is a definite positive.

Kudos to Phil Winstanley (plip) for organising another event - the prize draw was a nice surprise, even if I did win the CodeZone hat. Still, my 20 month old, Daniel, thinks it's great!

Now when's the next one?

Footnote: This was written using Windows Live Writer running on Vista RC1. I'm such a beta-whore! :-)

Wednesday, September 13, 2006

Change is a-comin'

I've been watching the progress of Mono for a while now, but until quite recently it's not been feature-rich enough to support porting my ASP.Net projects.

In this blog entry, Miguel de Icaza highlights how SplendidCRM was ported in a couple of hours thanks to a VMWare image of a fully-configured Mono development environment.

This is something I'm going to HAVE to install and play with - being able to deploy ASP.Net web sites on Linux, or even better virtualised Linux instances is going to be a very cost-effective and scalable solution - particularly if you add Amazon's Elastic Compute Cloud for dynamic scalability.

Tuesday, September 12, 2006

ATLAS going mainstream (and other entertainment)

In this blog entry, Scott Guthrie gives us the low-down on Microsoft's plans for actually releasing ATLAS as a supported product. This can only be good news, as it means that the technology will now get 10 years of support from Microsoft. The only down side is that to accelerate the release schedule, what's currently available as two products (ATLAS and the ATLAS Control Toolkit) will get busted into 3 or more - the balancing act being that of having a slightly harder maintenance process versus much better support.

On a related note, I'm looking forward to the VBUG Special Non-Member Event at QA Training in Stockport tomorrow evening . Titled "Flirting with AJAX with Gary Rowntree", it promises to demonstrate how to develop an IM application using ATLAS.

I wonder whether anyone's done any worked examples of integrating intranet-based applications with Sharepoint, Communications Server et al for presence management and embedded communications - seems to me that this is exactly what "joined up" applications are about. If you're going to be at the event, give me a wave.

Friday, September 01, 2006

Visual Studio .NET 2005 Keyboard Shortcuts

In his blog, "mapo" (a Microsoft consultant) links to handy Visual Studio .NET 2005 Keyboard Shortcuts as well as to a macro to generate the printable crib-sheet.

This has been around for a while, but kudos to Jeff Atwood of Coding Horror for this handy helper. His "recommended reading" is excellent too - its contents will be gracing my Amazon wish-list shortly, and should do for any serious / professional developer. Although, as one commenter points out, it doesn't include the "Gang of Four" book, nor my recommendation, Howard & LeBlanc's Writing Secure Code.

Thursday, August 31, 2006

Making editing TFS Build Types easy

Via a fairly convoluted route, I came across this add-in for Visual Studio 2005 today.

The Attrice Corporation Team Build Sidekick is a freeware (yes, really!) source-available add-in that lets you check out and edit a Team Build project as easily as you might any other source file.

No longer do we have to go and find the file in Source Control Explorer! Huzzah!

TFS and remote working

I've been using TFS at work for a few months now, and am pretty impressed with it.

My only real problem is with taking work home - at the moment it's a matter of copying via a memory stick, but that causes problems as VS relies on the readonly file state to determine whether a file has been changed.

This article by Martin Woodward details what will probably be the way forward for me - a VPN to home and a local TFS proxy - letting me keep my workstation and laptop in sync at home.

I'll probably have to use a virtual server instance tho', rather than having another server in the house.

For working disconnected on the laptop, Dave Glover gives the solution to preventing your copy of VS from connecting to TFS in this blog article. Unsurprisingly, it's a simple registry hack.

Deep Team Server joy will be mine! ;-)

Wednesday, June 21, 2006

The Power of Predicates

I ran up against a problem I'd not encountered before today - how to use the Find method on a generic List. The MSDN documentation is less than enlightening, but I found an excellent article entitled "Using generics to manage a collection of objects" byAmirthalingam Prasanna on simple-talk.com.

Amirthalingam covers the subject in detail, but I thought I'd share my reference implementation (and put it up somewhere that I can find it when I forget how to do this!). Purple elipses ( ... ) indicate where the finished code continues.

We'll implement a simple C# console application to start with to act as the framework for our reference implementation.
using System;
using System.Collections.Generic;
using System.Text;

namespace List_Find_Predicate_Test
{
class Program
{
static void Main(string[] args)
{
}
}
}
Next, let's define a "complex" class against a List of which we will search - we'll do this as a private inner class within our framework:
...
class Program
{
private enum Gender
{
Male,
Female
}

private class Criteria
{
public string Field;
public Type DataType;

public Criteria(string theField, Type theDataType)
{
this.Field = theField;
this.DataType = theDataType;
}
}
...
}
...
You'll notice I've spiced things up with a custom enumeration used within the Criteria class. Next, let's add some code to the Main method to build us a list of criteria objects:
...
static void Main(string[] args)
{
List<Criteria> critList = new List<Criteria>();
critList.Add(new Criteria("Name", typeof(System.String)));
critList.Add(new Criteria("Age", typeof(System.Int16)));
critList.Add(new Criteria("Gender", typeof(Gender)));

Console.WriteLine("List has {0} entries...", critList.Count);

// TODO: Search the list
...
}
...
Simple enough so far. The complexity happens in providing a mechanism to let the List.Find method operate - this is where Predicate classes come in. Predicates are analagous to Delegates - they effectively implement a call-back to a method that performs the comparison, and it is this call-back that the Find method uses to find matching elements in the List.

Let's add a quick search of the List, and get the type assigned to the "Name" criteria:
...
static void Main(string[] args)
{
...
// Search the list
Criteria crit = FindCriteriaByName(critList, "Name");
Console.WriteLine("Name criteria has type {0}", crit.DataType.Name);

// TODO: Search without having to use a helper method
...
}

// TODO: Implement FindCriteriaByName
...
OK - that was easy enough - just your common-or-garden-variety top-down programming so far. But now we get to the meat of the issue - the implementation of the FindCriteriaByName method - and this is where Predicates are used.

The key to Predicates is that they reference a class - in this case a class that is dedicated to filtering a List. We'll implement this as another private class within the program framework. This filter class is as simple as they come, taking a string parameter for its constructor, and exposing just one method FilterByField.
...
class Program
{
...
private class CriteriaFieldFilter
{
private string criteriaField;

public CriteriaFieldFilter(string fieldName)
{
criteriaField = fieldName;
}

public bool FilterByField(Criteria crit)
{
return (crit.Field == criteriaField);
}
}
...
}
...
You'll notice that the critical FilterByField method accepts a Criteria object as its parameter - when we call this class through a Predicate, this is the method that will be used to perform the filtering. So we can now finally implement the filter method:
...
class Program
{
...
// Implement FindCriteriaByName
private static Criteria FindCriteriaByName(List<Criteria> theList, string theName)
{
CriteriaFieldFilter searchFilter = new CriteriaFieldFilter(theName);
Predicate<Criteria> searchPredicate = new Predicate<Criteria>(searchFilter.FilterByField);
Criteria crit = theList.Find(searchPredicate);
return crit;
}
...
}
...
So our filtermethod starts by instantiating an instance of our filter class tailored with the field name passed in the theName parameter. The Predicate is then created against a pointer to the FilterByField method of that instance, and in turn that Predicate is used with the List.Find method to return the matching entry.

But is there a more compact way rather than having to implement the helper method at all? Of course there is! We just compact the code into an in-line function, thus:
...
static void Main(string[] args)
{
...
// Search without having to use a helper method
crit = critList.Find(new Predicate<Criteria>((new CriteriaFieldFilter("Gender")).FilterByField));
Console.WriteLine("Gender criteria has type {0}", crit.DataType.Name);
...
}
...
Rather harder on the eye, but more compact. I'd imagine that something could be done with Anonymous classes/methods to simplify this further, but that's a topic of research for another time.

Phew! A complex topic for just performing a Find in a List, but it does allow us to write any kind of matching algorithm we like working against just a single T instance and they use that matching algorithm to work with an entire List - that's the power of Predicates.

Thursday, June 15, 2006

Visual Studio Managed Code Analysis (FxCop) : FAQ: Why does FxCop warn against catch(Exception)? [Nick Guerrera]

In his recent posting titled "FAQ: Why does FxCop warn against catch(Exception)?":, Nick Guerrera does a great job of explaining best practice in exception handling.

I’ve heard a lot of arguments against DoNotCatchGeneralExceptionTypes, but they generally boil down to one or both of the following:
  • “If I call an API which doesn’t document which exceptions it can throw, then I have no choice but to catch all possible exceptions!”

  • “My application needs to be robust; it can’t crash just because of an exception that I forgot to handle!”
Well worth reading and thinking about how you code your exception handling routines - I know for one I use catch (Exception e) w-a-y too much!

Thursday, June 01, 2006

SOA, Autonomy and Caching

In the latest posting in his blog, Clemens Vasters gives an excellent reminder about what SOA really means for a developer or architect, and of some of its history.

But it's the pragmatism that Service Autonomy doesn't really matter under the hood because behind the service boundary is a private domain and "none of your business" to the outside world.

Finally, he makes some good points about caching, and particularly about passing forward cache validity information along with the data so that a client of a service can make an intelligent caching decision.

All well worth keeping in mind when, as I, you're building a large distributed system - find it here.