2
votes

At out company, we use NuGet to version our internal libraries. Every commit to a library triggers the build server, which churns out a new NuGet package and uploads it to our internal feed.

This works pretty well for us, but we often run into an issue with the WinForms designer, where it would refuse to load a form with an error message like this:

Die Datei oder Assembly "UILib, Version=1.0.0.906, Culture=neutral, PublicKeyToken=null" oder eine Abhängigkeit davon wurde nicht gefunden. Das System kann die angegebene Datei nicht finden.

(Roughly: The file or Assembly "UILib, Version=1.0.0.906, Culture=neutral, PublicKeyToken=null" or one of its dependencies could not be found. The system cannot find this file.)

This is only a designer issue though - the application will build without a problem and will run as intended.

This is the problem, but now you need some valuable context to make any sense out of it. The form that I'm trying to open is part of an application (let's just call it App), and it contains a UserControl which is part of our product-specific UI library (ProductUILib). That library in turn references our general-purpose UI library (UILib). However, the application itself also depends on UILib directly.

Both UILib and ProductUILib are provided through their own NuGet packages. So, the simplified dependency graph is like this:

App ----> ProductUILib ----> UILib
 |                             ^
 ------------------------------|

All is well as long as ProductUILib and App reference the same version of UILib (say, 1.0.0.906). However, if I modify UILib and then update my NuGet dependencies in App, App will get and reference the latest version of UILib (say, 1.0.0.932). ProductUILib was built against the older UILib, but that should be fine because all changes to UILib are backwards compatible, and we don't have strong names for those libraries either. And in fact, building and running App works fine. But the designer is now broken for the affected form and shows the error message I mentioned above.

To solve the issue we have to update ProductUILib's NuGet packages as well so that it in turn builds against the latest UILib, and then update App's dependencies once more to get the new ProductUILib. That quickly gets tedious though, especially with more libraries and dependencies.

I tested in both VS 2010 and the latest VS 2013, the new one shows the exact same behaviour.

Do you have any suggestion how we can avoid this issue?

1

1 Answers

2
votes

We managed to solve the problem by changing our strategy for using AssemblyVersion, AssemblyFileVersion and AssemblyInformationalVersion.

We automatically generate the last part of our version numbers on every build, by setting it to the current SVN revision number. This generated version number (e.g. 1.0.0.906) used to go into both AssemblyVersion and AssemblyFileVersion.

The designer apparently takes issue with a mismatch of AssemblyVersion as assemblies with differing AssemblyVersions are deemed incompatible. However, the normal loading process for assemblies without strong name doesn't mind the mismatch, so building and running the program works. So the designer is just a bit more picky.

The solution was to use a fixed value for AssemblyVersion that we will only update on breaking changes. The generated version number now goes to both AssemblyFileVersion and AssemblyInformationalVersion. That last one is important because NuGet will always fill its .nuspec $version$ placeholder from AssemblyVersion unless AssemblyInformationalVersion is present to override it, and we want to generated version number to be used for our NuGet packages.

So in summary:

  • Only update AssemblyVersion for breaking changes
  • Use AssemblyInformationalVersion for the number that should go into your NuGet Package