Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which dll files of ASP.NET web application does IIS load?

Tags:

.net

asp.net

iis

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.

like image 258
Arkadiusz Kałkus Avatar asked Dec 11 '22 20:12

Arkadiusz Kałkus


2 Answers

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".

like image 157
CodingWithSpike Avatar answered Jan 01 '23 00:01

CodingWithSpike


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.

like image 31
Luaan Avatar answered Jan 01 '23 00:01

Luaan