Skip to content

GitVersionTask executes GetVersion too late for the XAML compiler #1465

@jbaehr

Description

@jbaehr

Short Version

The XAML targets consume the "AssemblyVersion" property, GitVersionTask's GetVersion exports it, but due to a missing dependency declaration MSBuilds executes GetVersion after the XAML stuff.

Some Background

The XAML Markup Compiler (from PresentationBuildTasks via target "MarkupCompilePass1") generates C# code which loads the XAML at run time from a managed resource. This resource is identified by an URI, containing the assembly where the resource is embedded and the path towards it.
Without the "AssemblyVersion" property being set, this URI contains only the simple assembly name, without version information. This works as long as the assembly is only loaded once. However, in e.g. advanced plugin scenarios it may happen that the same (strong named) assembly is loaded several times in different versions. In those cases the XAML resource can only be located when the version information is available in the URI.
The consequence is an exception like the following:

System.Windows.Markup.XamlParseException: 'The invocation of the constructor on type 'Foo.Bar.Views.MyControl' that matches the specified binding constraints threw an exception.' Line number '115' and line position '18'. ---> System.Exception: The component 'Foo.Bar.Views.MyControl' does not have a resource identified by the URI '/Foo.Bar;component/views/mycontrol.xaml'. 
 at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator) 
 at Foo.Bar.Views.MyControl.InitializeComponent() in D:\...\Views\MyControl.xaml:line 1 
 at Foo.Bar.Views.MyControl..ctor() in D:\...\Views\MyControl.xaml.cs:line 27 
 --- End of inner exception stack trace --- 
 at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri) 
 at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri) 
 at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream) 
 at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator) 

With the "AssemblyVersion" property set to "1.2.0.0", the generated URI will look like this /Foo.Bar;V1.2.0.0;component/views/mycontrol.xaml and thus also work when Foo.Bar.dll in v1.1.0.0 is loaded in parallel.

Proposed Solution

The MSBuild files distributed with the GitVersionTask should add "GetVersion" as dependency of "MarkupCompilerPass1":

<!--
    Ensure GetVersion runs prior to XAML's Markup Compiler in order to have the assembly version available.
    Otherwise the generated resource URI's are ambiguous when multiple versions are loaded simultaneously (i.e. in plugins)
-->
<MarkupCompilePass1DependsOn>$(MarkupCompilePass1DependsOn);GetVersion</MarkupCompilePass1DependsOn>

I've verified this with Beta.13 where I placed those lines in GitVersionTask.targets, where we already have GetPackageVersionDependsOn. With the reorganizations in Beta.14, I think GitVersionCommon.props is the right place (to be checked).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions