Tuesday, January 6, 2015

Assembly Not Found - .net runtime error

If you use a build server to build via msbuild and deploy to a web server, you may come across an error where some assembly is not found after the built code is run on the server. It works locally and perhaps even on other servers, but just not server x.

Following are my explanation of how this happens and what options are available to resolve this issue.

First off, when msbuild is run, it typically gets some information from the project file about how the project should be built. The project file is XML and contains some build details such as how to run nuget and which build targets to use during execution.

Build targets (.targets) are files that can be included in other build scripts which are XML files that declaritively set properties, run build tasks, and some other voodoo. Some examples of tasks are compile via csc, copy files, and run nuget.

One build target that is run is Microsoft.Common.targets. This file contains information about where to look for dependent assemblies (references). It directs msbuild to look in all sorts of places like program files directories, the current target framework directory, the GAC, and several others. The first assembly it finds is the one that will be used.

When a referenced assembly is found installed on the machine, msbuild makes an assumption that there is no need to copy that assembly to the bin. So, when the build server has the assembly installed it is not copied to the bin even if copy local is set to true (I've only witnessed this for nuget package refs so far and haven't thoroughly tested if true for other assemblies).

After the projects are built and all staged into the build drop folder, they can be copied out to the target server. Or perhaps built directly out to the target server, whichever you do. Now suppose the target server does not have the referenced assembly that the build server has installed wherever. This will be a runtime error! And who knows when it will rear it's ugly head!

Here's what can be done:

Option 1: uninstall anything that's become a nuget from your build server and let nuget pull it in.
Option 2: install the same components on all target servers.
Option 3: customize the build script to always copy local somehow (haven't explored this but seems viable)

Really, just do option 1. The others aren't better. Make sure those assemblies are set to copy local and that package restore is on.

msbuild reference-

Example targets file from the Roslyn compiler

No comments:

Post a Comment