Tuesday, 1 June 2010

TFS Branching

A good resource here

and in the "ranger" TFS branching guide here

SAK reference in VS projects

And here's why

Visual Studio project GUIDS

Some care needs to be taken when a large number of people are contributing to a solution... When a VS project is created a new (unique of course) GUID is assigned to the project, when the project is part of a solution the GUID is used to reference the project by VS.

Here comes the trouble... If VS sees inconsistency, i.e. it spots a project GUID within a solution which is cannot resolve
1. Because another project exists with the same guid (in which case VS will generate a new guid for one of these projects)
2. Because another user has the same project or the same solution but either the project or the project reference in the solution has a different GUID to the one you have and they checked-in! In this case (with automatic check-out configured) VS will correct the mistake and the user may not have been aware (or not bothered to check) when they checked-in their changes.

Either way great care is required, we've seen this when people create a new project by copying-and-pasting an existing project.

If it's not noticed, or not acted upon, it can cause a nasty circle of check-in, check-out, change, check-in amongst a large group or between teams. This causes a great deal of confusion with a lot of developers not familiar with the details.

The way to fix this is to make sure all projects within a solution have unique guid, and that a project referenced in the solution has the correct guid (note because the project can be changed by VS, you have to look carefully in history to get the correct guid, which other people may still be referencing).

This situation applies to scenarios where lot's of "project references" exist in the solution and where the solution is stored in source control.

Thursday, 22 April 2010

MS Build, deployment of websites

I had a bit of trouble with this, finally coming accross this blog: blog.m.jedynak.pl

Two things to watch out for with _CopyWebApplication

1. You need to resolve the references by making an explicit call to "ResolveReferences"
2. You need to specify both the output / virtual directory path *and* the web project output path, if you don't (and as noted in the linked blog post) the references will only get copied one level deep!

However, once it's working, is well worth the effort and of course invaluable for that continuous integration!!!

<MSBuild 
Projects ="%(WebProject.path)"   
Properties ="OutDir=$(DestFolder)\%(WebProject.Identity)\BIN\;
WebProjectOutputDir=$(DestFolder)\%(WebProject.Identity)\"
Targets="ResolveReferences; 
        _CopyWebApplication" 
/>




Update: We have has some issues with this approach, principle is what appears to be a bug within the ResolveReferences target.

We always build a solution containing the web services to deploy and we do this first.

However (and I am not sure exactly what triggers this) the corecompile target can be called if the framework thinks an assembly is "out of date" and needs re-compliling. As I say this shouldn't happen for us given we build the solution up-front, but sometimes it does.

When this does happen (on a project by project basis) and if it happens where a project has either a direct or indirect reference to another project AND that other project has a binary/file ref to a MS assembly - in this example System.Web.Services then we hit some trouble.

The corecompile will call the compiler directly passing in a list of commands including all the dependancies, but in this case System.Web.Services is a second level dependancy (it's not directly referenced by the assembly being built, but is by a child assembly) and it doesn't get added causing an exception.

I am still not sure if there's a fix for this, but this problem was in context of some old vs2005 projects and I have a feeling this wouldn't be an issue with 2008 and 2010.

Anyway for now we are using a Folder.Copy target (given that we manage GAC dependancies and we pre build the solution) and this is fine for us, for now.

Thursday, 8 April 2010

Testing biztalk maps where the xsl calls out to deployed components

It's quite common to write an xsl which obtains values from or makes use of existing .net lib functions

Example

<xsl:stylesheet version="1.0"
 xmlns:bjg="http://ns.com/myext"
                
    exclude-result-prefixes="bjg">

    <xsl:template match="/">

        <SomeOutput>
            <xsl:value-of select="bjg:SomeMethod()"/>
        </SomeOutput>
        
    </xsl:template>
</xsl:stylesheet>

Where the extension(s) are defined in a "mapper extension" xml file (pointed from the btm map file)

<Extensionobjects>

    <ExtensionObject
       Namespace="http://ns.com/myext"
       AssemblyName="MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=123456abc123a123"
       ClassName="MyAssembly.MyClass" />

</ExtensionObjects>

However it's less straight forward to test the xsl outside of Biztalk.

The xslt-compiled-transform requires information relating to these assemblies along with the test xml instance.

The orginal map extensions file can be utilised to do this with the following code, which loads an xsl argument list to be applied to the xsl-compiled transform (possibly to be run from a test)

XmlDocument xmld = new XmlDocument();
            xmld.Load(mapperExtensionsFilePath);

            XmlNodeList ns = xmld.SelectNodes("/ExtensionObjects/ExtensionObject");

            // load each extension
            foreach (XmlNode n in ns)
            {
                // get attributes
                string assemblyName = n.SelectSingleNode("@AssemblyName").InnerText;
                string theNamespace = n.SelectSingleNode("@Namespace").InnerText;
                string className = n.SelectSingleNode("@ClassName").InnerText;

                // find type
                foreach (Type t in Assembly.Load(assemblyName).GetTypes())
                {
                    if (t.FullName.Equals(className) )
                    {
                        xslArgs.AddExtensionObject(theNamespace, Activator.CreateInstance(t));
                        break; 
                    }
                }
            } // get next extension

Thursday, 4 March 2010

Biztalk gotcha?

BTS 2006

Exception type: TypeInitializationException
Source: MyNS.MyService

Additional error information: Field not found: 'ReferencedAssembly_.Type.Method'.

Exception type: MissingFieldException
at MyNS.MyService..cctor()

****

Biztalk Assembly 1: Assm1.dll
Biztalk Assembly 2: Assm2.dll

Assm1 references Assm2

Assm2 contains a "web reference" to a service, but in this scenario Assm1 has referenced Assm2 to access a shared type, it doesn't care about the web ref.

Now, say I updated the web ref and build Assm1, which will in turn cause Assm2 to be built...

I need to ensure *both* assemblies get deployed...

Because the web service "proxy" will have been propogated into Assm1.

This isn't a problem until the web service contract is changed - a breaking change, say a method is added.

If this happens and only Assm1 is deployed, then I'll get a missing field exception in the Assm1 constructor as the proxy definition there will be expecting a field in the proxy which doesn't yet exist on the target machine!
In order to deal with this, I'd need to deploy both assemblies.

A better idea would be to have an assembly wrapping the web reference and nothing else, so I'm only referencing this assembly if I actually need the web proxy!

Snippet of constructor in Assm1

static MyType()
{
__access = 1;
__execable = false;
_serviceId = HashHelper.HashServiceType(typeof(MyType));
_lockIdentity = new object();
_portInfo = new PortInfo[] { new PortInfo(new OperationInfo[] {
Assm2WebProxy.Method1, Assm2WebProxy.Method2, Assm2WebProxy.Method3 ....

Sunday, 7 February 2010

If a class implements IDisposable then an instance of that class should be wrapped in a “using” (c# or the vb equivalent) which guarantees dispose… otherwise Dispose should always be called explicitly; if dispose is implemented the developer meant that specific cleanup logic should always execute. Usually Dispose is implemented for cleaning un-managed resources, rather than managed.

Where Close* is also implemented, then Dispose should always call Close as part of the dispose implementation and because we’re all cynics reflector is our friend – see reflected code snippets for SQL Data Reader and SQL Connection below.

Obviously with view of connection pooling, closing a connection doesn’t necessarily mean that the resource is free

Framework2.0 SqlConnection

public void Dispose()
{
    this.Dispose(true);
    GC.SuppressFinalize(this);
}

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    }
    this.DisposeMe(disposing);
    base.Dispose(disposing);
}


Framework2.0, SqlDataReader

public void Dispose()
{
    this.Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
    if (disposing)
    {
        this.Close();
    }
}


BTW whilst I’m in favour of understanding the inner working of objects that you code against, it’s my opinion that better code is explicit code, so I would be in favour of explicit close() for all instances where close() should be called, even if I know – as a developer – that close() is implicit.

I believe this also guards against future changes to the framework, in later versions.



* Close would usually be implemented because it’s (conceptually) cheaper to re-open a closed connection (for example) than allocate a new one which would also appear to be the consensus.