WCF, RouteTables and Castle Windsor

 

We are using the routing functionality to give our RESTful WCF service nice endpoints, however I ran into trouble, none of our services were being injected.

The service had two constructors which seemed odd, an empty one and one with dependencies specified…

public Api()
{
}

public Api(IBasket basketService)
{
    _basketService = basketService;
}

The injected services were NULL, so I removed the public constructor and got:

image

This sounds like the default WCF factory at work, checking the SVC files we get:

<%@ ServiceHost 
    Language="C#" 
    Factory="Castle.Facilities.WcfIntegration.DefaultServiceHostFactory, Castle.Facilities.WcfIntegration" 
    Service="MyProject.Api" 
%>   

That’s also configured correctly, but we have overridden the default routing, let’s take a look at that:

RouteTable.Routes.Add(new ServiceRoute("Api", new ServiceHostFactory(), typeof(Api)));

That looks like the default WCF factory to me… Doh! Let’s fix that up…

RouteTable.Routes.Add(new ServiceRoute("Api", new DefaultServiceHostFactory(container.Kernel), typeof(IApi)));

Great, we are now using the windsor factory, and we can remove the default parameter-less constructor from our API service.

XmlLists with Psake / Powershell

On a POSH roll here, this time I needed to list out the Include attributes for references in an msbuild file. Let’s take a look at the POSH script equivalent of XmlList:

function xmlList([string]$file, [string]$xpath, [hashtable]$namespaces) { 
    [xml] $fileXml = Get-Content $file 
    $xmlNameTable = new-object System.Xml.NameTable
    $xmlNameSpace = new-object System.Xml.XmlNamespaceManager($xmlNameTable)

    foreach($key in $namespaces.keys)
    {
        $xmlNameSpace.AddNamespace($key, $namespaces.$key);
    }
    $nodes = @()
    $node = $fileXml.SelectNodes($xpath, $xmlNameSpace) 
    $node | ForEach-Object { $nodes += @($_.Value)}
    
    return $nodes
}

Now to use this we can do this:

$namespaces = @{ "xsi" = "http://schemas.microsoft.com/developer/msbuild/2003"}
$xpath = "//xsi:Reference/xsi:HintPath/../@Include"

$nodes = xmlList "$examplesdest_dir\NBehave.Examples.csproj" $xpath $namespaces

And it gives us a list of the references in the msbuild file.

image

XmlPoking vsixmanifests with Psake / Powershell

 

Nant had some very useful XmlPoke and XmlPeek tasks for working with xml files. When manually installing visual studio plug-ins, the vsixmanifest needs to have some fields prodded to work correctly, specifically the InstalledByMsi and Version.

So here’s a POSH version of XmlPoke:

function xmlPoke([string]$file, [string]$xpath, $value, [hashtable]$namespaces) { 
    [xml] $fileXml = Get-Content $file 
    $xmlNameTable = new-object System.Xml.NameTable
    $xmlNameSpace = new-object System.Xml.XmlNamespaceManager($xmlNameTable)

    foreach($key in $namespaces.keys)
    {
        $xmlNameSpace.AddNamespace($key, $namespaces.$key);
    }
    
    $node = $fileXml.SelectSingleNode($xpath, $xmlNameSpace) 
    if ($node) { 
        $node.InnerText = $value 

        $fileXml.Save($file)  
    } 
}

 

And the usage for vsixmanifests is below, you will need to adjust the namespaces based on the xml you are prodding.

$namespaces = @{ "vsx" = "http://schemas.microsoft.com/developer/vsx-schema/2010"}
$xpath = "/vsx:Vsix/vsx:Identifier/vsx:"
xmlPoke "$destination\extension.vsixmanifest" $xpath"InstalledByMsi" "true" $namespaces
xmlPoke "$destination\extension.vsixmanifest" $xpath"Version" $version $namespaces

ILMerging assemblies with Psake / Powershell

 

On NBehave I am migrating the existing build framework from Nant over to Psake, and am thoroughly enjoying the ability to debug and step through my build scripts.

We needed to merge some of our output assemblies before packaging, and this was extremely easy in POSH:

function ilmerge($key, $directory, $name, $assemblies, $extension)
{    
    # Create a new temp directory as we cannot overwrite the main assembly being merged.
    new-item -path $directory -name "temp_merge" -type directory -ErrorAction SilentlyContinue
    
    # Unfortuntately we need to tell ILMerge its merging CLR 4 assemblies.
    if($framework -eq "4.0")
    {
        Exec { tools\ilmerge\ilmerge.exe /keyfile:$key /out:"$directory\temp_merge\$name.$extension" "$directory\$name.$extension" $assemblies /targetplatform:"v4,$env:ProgramFiles\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0" }
    }
    else
    {
        Exec { tools\ilmerge\ilmerge.exe /keyfile:$key /out:"$directory\temp_merge\$name.$extension" "$directory\$name.$extension" $assemblies }
    }
    
    Get-ChildItem "$directory\temp_merge\**" -Include *.dll, *.pdb | Copy-Item -Destination $directory
    Remove-Item "$directory\temp_merge" -Recurse -ErrorAction SilentlyContinue
}

The parameters are straightforward and as you’d expect, here’s an example usage:

$key = "$solution_dir\NBehave.snk"
$directory = "$build_dir\dist\v$framework"
$name = "NBehave.Narrator.Framework"

$assemblies = @("$directory\gherkin.dll", 
                "$directory\NBehave.Spec.Framework.dll", 
                "$directory\Should.Core.dll", 
                "$directory\Should.Fluent.dll")

ilmerge $key $directory $name $assemblies "dll"

 

The extension should be “.dll” or “.exe” depending on what the main artifact your trying to merge is.

Newer Posts Older Posts