4

I couldn't find any information about it. Does anybody know whether IIS load all dlls in bin directory of web application or all dlls in any directory or maybe only directories referenced by project (in this case how it determines which dll is "master")?

I've just had a situation where someone didn't remove all files from web application directory before deploying new version, while some dll was renamed. This redundant dll was in bin directory of MVC 4 web application.

Arkadiusz Kałkus
  • 17,101
  • 19
  • 69
  • 108

4 Answers4

8

It doesn't load any DLLs automatically.

Every DLL it loads is directly related to a request. First, Global.asax is compiled (which may load some DLLs from bin). Then, whatever HTTP modules and HTTP handlers are defined in web.config (there's some overlap with the previous step). Then the final aspx/asmx/... Some others might go for the ride as part of the configuration or something like that, but all the DLLs that are loaded are always loaded explicitly.

Thus, there is no "master" DLL. web.config, Global.asax and the actual requested file are the ones to decide what's actually going to happen. If you need to have a particular DLL loaded (and you don't simply have it referenced), you need to do it yourself.

EDIT:

Since this is a bit complicated, let me expand a bit.

The main thing to keep in mind here is that ASP.NET is always dynamically compiled - at least to an extent. At the very least, you always have to compile Global.asax - no way around it. Now, dynamic compilation in ASP.NET has an important feature - it's out-of-process (at least for the legacy compiler - I'm not sure about Roslyn+). So whatever the compiler does to find references etc., doesn't actually reflect what's loaded to the worker process itself - and to your application domain in particular.

The dynamic compilation is handled by the BuildManager class on the .NET side - http://referencesource.microsoft.com/#System.Web/Compilation/BuildManager.cs,fb803c621f3806a8. Since you asked about a "master DLL", the most relevant bit would be the code that handles Global.asax compilation, which is one of the starting points of any ASP.NET application. The very initial compilation is handled by the EnsureTopLevelFilesCompiled method. Looking through the code, you can easily see the first steps:

CompileResourcesDirectory();
CompileWebRefDirectory();
CompileCodeDirectories();

...

CompileGlobalAsax();

Most of this is slightly different for web sites vs web projects, as well as for pre-compiled sites, but we can pretty much ignore that. Now, the code isn't the simplest code in the world, but basically, it boils down to producing a bunch of assemblies - about one assembly per code directory. Again, this is done out of process - while the compiler has to load the binaries in bin, they are not necessarily loaded into the ASP.NET worker process. Instead, only the necessary references are actually loaded.

The main thing to take from this is that the dynamic compilation will indeed do a lot of resolving to help you (after all, you don't even know the name of the dynamic assembly where your types are compiled, so you can't specify it!) - but that doesn't mean that all the assemblies in bin are loaded in your ASP.NET application domain. The easiest way to check this is to add an empty assembly that isn't referenced anywhere to bin, and then print out AppDomain.Current.GetAssemblies - you will see that while the file was indeed touched during the compilation process, it wasn't loaded into the ASP.NET application domain. You need to bear this in mind if you ever try to implement some dynamic module loading in ASP.NET - you need to load those assemblies yourself.

You can tweak the way the compilation works in your web.config (especially the global one) - for example, by default, all the assemblies in bin are loaded for compilation purposes, but you can use the system.web/compilation/assemblies tag to cherry pick whatever you want.

Luaan
  • 62,244
  • 7
  • 97
  • 116
  • @CodingWithSpike Old-school ASP.NET compilation is actually out-of-process, so it doesn't load any assemblies to the worker process. After the `App_Global.asax` assembly is built, the relevant references are loaded to the worker process. The key thing to remember is that the build process *isn't* part of the worker process - it can bite you sometimes. There's some differences between a web project and a web site, but it doesn't really matter much here. – Luaan Oct 16 '15 at 13:06
8

As an experiment I made a new ASP.NET Webforms project, and deployed it to IIS. I then made a 2nd .net class library, and copied the .dll file to the web app's \bin folder (the class library is not referenced or used anywhere in the ASP.NET app).

I started up SysInternals ProcMon, recycled the app pool and web site in IIS, and requested the site in a browser.

w3wp.exe does indeed read the class library .dll file on first page request.


This MSDN page also states:

You can store compiled assemblies in the Bin folder, and other code anywhere in the web application (such as code for pages) automatically references it. A typical example is that you have the compiled code for a custom class. You can copy the compiled assembly to the Bin folder of your Web application and the class is then available to all pages.

Assemblies in the Bin folder do not need to be installed in the Global Assembly Cache (GAC). The presence of a .dll file in the Bin folder is sufficient for ASP.NET to recognize it.

Which does seem to imply that ASP.NET will reflect over the assemblies it finds in \bin and automatically load them.


Interestingly, even if you put a non-.net file (I copied twain.dll from C:\Windows) into your ASP.NET bin folder, those files are also read. The runtime seems to just ask the filesystem for \bin\* and loops over the files to check for .NET assemblies to load.


I also noticed that if you add this to your web.config file:

  <system.web>
    <compilation targetFramework="4.5">
      <assemblies>
        <clear />
      </assemblies>
    </compilation>

Then the page will no longer run, with the error

Could not load type 'WebApplication1.Global'.

So it seems that the runtime no longer loads those classes from the assemblies. However, the runtime still reads the non-referenced console application .dll and non-.net assembly twain.dll off the drive.

So, the answer comes down to what you mean by "loads all dlls" ... If you mean makes available in the runtime, then the answer is sort-of "no" if you specify your own system.web | compilation | assemblies but the default is to load all. But if you mean what files are physically read, then "yes".

CodingWithSpike
  • 42,906
  • 18
  • 101
  • 138
  • Thank you very much. Great explanation. – Arkadiusz Kałkus Oct 16 '15 at 12:27
  • Try adding reflection to your experiment. Add another .NET library, and don't reference it anywhere. Print out `AppDomain.CurrentDomain.GetAssemblies()` - your assembly isn't there (at least not in a web project - it might be in a web site, I haven't worked with those in a long time). The assemblies in `bin` are inspected, yes - but they aren't loaded unless necessary. – Luaan Oct 16 '15 at 12:57
  • That's interesting. I wonder if it reflects over all the assemblies and maps class names to assemblies, so when a class is needed it knows which assembly to load into the domain. I guess the definition of "loaded" is unclear in this situation. – CodingWithSpike Oct 16 '15 at 13:02
  • @CodingWithSpike It doesn't look like it on the surface, but the building is actually completely separate from the ASP.NET worker process - in the end, it "simply" calls `csc.exe`. The generated assemblies (e.g. `App_Global.asax`) are then loaded to the worker process, along with their required references. It's really a bit of black magic :) I expect that the new Roslyn-based ASP.NET compiler will behave differently, but I haven't done any testing with that. – Luaan Oct 16 '15 at 13:07
  • @CodingWithSpike If this looks interesting to you, have a look at the `BuildManager` class on .NET reference source (http://referencesource.microsoft.com/#System.Web/Compilation/BuildManager.cs,06055063bc401aeb). AFAIK it handles *all* the dynamic compilation of ASP.NET. The especially relevant point here being the `BuildManager.GetType` method, which tries quite hard indeed to find the appropriate assemblies - some of which are already dynamically compiled assemblies somewhere in temp (based on e.g. the `aspx` files). – Luaan Oct 16 '15 at 13:10
0

Yes asp.net loads any dlls present in your bin directory .

I have recently written a blog on this as I ran into an issue with dlls which were not used in my project. Please refer this blog ,trying to discuss couple of other common scenarios as well.

Rohith
  • 5,527
  • 3
  • 27
  • 31
-1

Asp.net loads all dlls in the bin directory.

Don
  • 6,632
  • 3
  • 26
  • 34
  • Any reference, documentation, or proof? – CodingWithSpike Oct 16 '15 at 11:59
  • 1
    Yes based on my past experience and found a Link to a similar question. I guess I should have posted that first. http://stackoverflow.com/questions/508034/how-to-stop-asp-net-from-loading-all-assemblies-from-bin-on-first-load – Don Oct 16 '15 at 12:07