Although developers often use the terms interchangably, there is a difference between a .NET Application Domain [microsoft.com] and an ASP.NET Application Pool [microsoft.com]. Regular .NET applications load assemblies into an application domain on demand.
ASP.NET has special behavior that will automatically load all assemblies in the /bin directory when the application domain loads or reloads.
An ASP.NET application domain will unload when any one of the following occurs:
- An update to web.config, machine.config or global.asax
- Any updates to the contents of the bin directory
- Exceeding the threshold specified by the config compilation numRecompilesBeforeAppRestart
- Changing physical path of the virtual directory
- An update to the CAS
- Restart of the web service
- An application sub-directories is deleted
Here is a simple script you can use to see what is currently loaded in an ASP.NET application domain:
<%@Page Language="C#"%>
<html>
<head>
<title>Currently Loaded Assemblies</title>
<style type="text/css">
table {border-collapse:collapse;}
td {vertical-align:top;border: 1px solid;margin:0px;padding:3px;}
th {vertical-align:bottom;border: 1px solid;background-color:#cccccc;margin:0px;padding:3px;}
</style>
</head>
<body>
<%
AppDomain currentDomain = AppDomain.CurrentDomain;
//Once monitoring CPU and memory of application domains in the current process is enabled, it cannot be disabled.
//System.AppDomain.MonitoringIsEnabled=true;
Response.Write("<table><tr><th>Current Domain</th><td>");
Response.Write(currentDomain.FriendlyName);
Response.Write("</td></tr><tr><th>Application Trust</th><td>");
Response.Write(Server.HtmlEncode(currentDomain.ApplicationTrust.DefaultGrantSet.ToXml().ToString()));
Response.Write("</td></tr><tr><th>Dynamic Directory</th><td>");
Response.Write(currentDomain.DynamicDirectory);
Response.Write("</td></tr><tr><th>Relative Search Path</th><td>");
Response.Write(currentDomain.RelativeSearchPath);
Response.Write("</td></tr>");
if (System.AppDomain.MonitoringIsEnabled)
{
Response.Write("<tr><th>Total Processor Time</th><td>");
Response.Write(currentDomain.MonitoringTotalProcessorTime);
Response.Write("</td></tr><tr><th>Total Allocated Memory</th><td>");
Response.Write(currentDomain.MonitoringTotalAllocatedMemorySize);
Response.Write("</td></tr><tr><th>Survived Memory</th><td>");
Response.Write(currentDomain.MonitoringSurvivedMemorySize);
Response.Write("</td></tr>");
}
Response.Write("</table>");
System.Reflection.Assembly[] assems = currentDomain.GetAssemblies();
Response.Write("<p>Currently Loaded Assemblies</p>");
int i=1;
Response.Write("<table><tr><th>#</th><th>Full Name</th><th>GAC</th><th>Dynamic</th><th>Code Base</th><th>Location</th></tr>");
foreach (System.Reflection.Assembly assem in assems)
{
Response.Write("<tr><td>");
Response.Write(i);
Response.Write("</td><td>");
Response.Write(assem.FullName);
Response.Write("</td><td>");
Response.Write(assem.GlobalAssemblyCache);
Response.Write("</td><td>");
Response.Write(assem.IsDynamic);
Response.Write("</td><td>");
try{
Response.Write(assem.EscapedCodeBase);
}catch{}
Response.Write("</td><td>");
try{
Response.Write(assem.Location);
}catch{}
Response.Write("</td></tr>");
i++;
}
Response.Write("</table>");
%>