VS2005 Web Project: Assembly referencing issue

May 19, 2007

no comments

We have encountered an interesting issue regarding assembly referencing from an ASP.NET web project in Visual Studio 2005. A developer in my team did the following: he added to a web-site a reference to a GAC installed assembly, lets call it Gac.dll. This GAC installed assembly had a file reference to another assembly which was not installed at the GAC, we shall call it Lib.dll, and we shall assume it is located in c:\lib.

Lets assume Gac.dll has the following code in it:

namespace Gac { public class GacObject { public void UseLib() { new Lib.LibObject().DoSomething(); } } }

And the developer in my team had code similar to this:

protected void Page_Load(object sender, EventArgs e) { new Gac.GacObject().UseLib(); }

At this point, Boom. Runtime exception:

Could not load file or assembly ‘Lib, Version=, Culture=neutral, PublicKeyToken=b51b3d0471344dda’ or one of its dependencies. The system cannot find the file specified.

Now, in order to understand why this happens, we first have to understand a very important thing:

An assembly does not store the locations of the DLLs it is referencing in its manifest.

That is, the reference in gac.dll to lib.dll would look like this inside the assembly manifest:

.assembly extern Lib { .publickeytoken = (B5 1B 3D 04 71 34 4D DA ) // ..=.q4M. .ver 1:0:0:0 }

No where does it say that we can find Lib at c:\lib. So when on Page_Load we are calling the UseLib method, the CLR has to load the Lib assembly at this point. For that to happen it needs to find it first. The CLR would look for the assembly in several places, including the Bin directory and GAC, but it won’t find Lib.dll in neither. And there’s no reason for it to know to search in c:\lib. Hence, an exception is thrown to our faces.

Now, why was it important to mention that this is a web project? Won’t the same thing happen for, say, a console application? Well, no. Say that we create a console application called MyApp, and reference Gac.dll in it, in which we will have the following code:

class Program { static void Main(string[] args) { new Gac.GacObject().UseLib(); } }

Running this will work like a charm. Not because the CLR acts differently for console applications, it is actually because the way Visual Studio compiles this project. In all projects which are not web sites, compiling in VS2005 means running the MSBuild script that is in our .csproj file. This script is actually smart enough to know that since Gac.dll is referencing Lib.dll, we will need it in our output directory (in MyApp case – bin\debug). Therefore it will copy Lib.dll and any other assemblies that Gac.dll is using (that are not installed in the GAC, that is) to this directory. Hence, when we run our program, the CLR quickly finds Lib in our bin\debug directory and everything works.

But when we compile our web site project, this does not happen, as it doesn’t run the standard MSBuild script (we don’t even have a .csproj file, remember?). It will actually work for assemblies that are not in the GAC – if you try and add a reference to nonGac.dll which is also referencing Lib.dll, Lib.dll will be automatically added to the site’s bin directory. Not on compile time, mind you. Visual Studio will do this at the moment we add the reference to nonGac.dll. For some unknown reason, the same doesn’t happen for a Gac.dll which is in the GAC, and therefore we get an exception at the moment we try to load Lib.dll.

Once we understand the problem, the solution is quite simple. We have to tell the CLR where to find Lib.dll. There are several things we can do:

  1. Manually add a reference to Lib.dll to the site’s Bin directory.
  2. Add Lib.dll to the GAC (best option, IMO).
  3. Tell the runtime where to search for the dll, using a configuration option.
  4. Switch to a Web Application Project and get all the standard MSBuild features.

Hopefully this wasn’t too confusing. The subject of assembly referencing and binding can give you quite a hell in .NET, so it is critical to have a good understanding of what is going on.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>