Assembly not loading for ASP.NET web application - asp.net

I have a web application which references an external DLL (lets call this productA.dll)
I have updated my GAC, my web.config, and my references, checked the versions and everything looks consistent.
However, when I run my application, methods that I use from productA.dll cannot be called, and I get a the specified module cannot be found error.
I tried creating a windows application and I can use productA.dll perfectly fine.
Observing the output window during run-time for the web application, I noticed that productA.dll symbols are not loaded. So I'm guessing that is why the module cannot be found.
The question is: why are the symbols not being loaded?
Any tips on the solution or diagnostics techniques would be greatly appreciated.

It's not a requirement that the assembly be in the GAC. I'd say to check the following:
Your assembly is in the website's bin folder.
Your assembly is referenced in the assemblies section of the web.config.
The assembly reference in the web.config has the correct version number.
By the way, symbols will only be loaded if you have the debug file (.pdb) along side the assembly.

Related

Partial ASP.net deployment issue - "Could not load assembly "App_Web_xxx.dll", make sure that it is compiled before accessing the page"

I am using Visual Studio 2017, and the application target .net framework is 4.5.2.
This application ABC (to which I am providing an enhancement) is already deployed and functioning pretty well.
Now that I have to only perform changes on 1 page (a simple condition change), I am planning to deploy only App_Web_xxxx in the ".\bin" folder.
After publishing the application using the "Precompiled" configuration, I was able to identify the respective App_web_xxx.dll file and copied in App. Server bin folder. Renamed it according to existing requestEdit.aspx file. All looks good till now, and interestingly, this App_Web_xxx.dll is common for multiple aspx files available under a common folder (users/request).
Once I try executing this code by accessing the website (respective aspx.cs UI file), it gives the error:
"Could not load assembly "App_Web_xxx.dll", make sure that it is compiled before accessing the page".
But the issue is This dll file doesn't break for any other aspx page available under the User/request folder, it is failing only for feature I modified.
What I have done apart from above mentioned way (considering usual way of partial deployment process):
Replaced requestEdit.aspx page and added new dll, by keeping old dll as is (which can be used by other aspx pages in deployment folder)
Error changed to:
Could not load assembly 'App_Web_xxx.dll, version=0.0.0.0, Culture=neutral, Publickey Token=null' or one of its dependencies.The system cannot find the file specified.
Replaced requestEdit.aspx page and added new dll, by removing old dll and renaming App_Web_xxx.dll in "Imports = Default.aspx, App_Web_xxx.dll" in all required aspx files (for which the old dll was removed)
If I am replacing the whole solution (except web.config) the solution works fine with no issues, the only problem comes when I am replacing only 1 .dll file.
All the solutions I found are providing information of IIS version or dll copying from Server to Dev, but my problem is I'm publishing on dev env (local machine) and partially deploying on the server.
Need help to resolve this issue as this is really inconvenient to deploy the whole solution just for 1 condition change!
Additional Info:
Page Properties --> MSBuild Options --> Allow this Precompiled site to be updatable (checked)

Where Does ASP.NET Store Assembly References Other Than web.config?

I am getting the classic exception
Could not load file or assembly 'XXX.Base, Version=11.0.0.0, Culture=neutral, >PublicKeyToken=xxxxxxxxx' or one of its dependencies. The located assembly's >manifest definition does not match the assembly reference. (Exception from >HRESULT: 0x80131040)
The assembly D:\xxx\xxxx\xxx\bin\xxx.xxx.xxx.xxx.dll was found but could not >be loaded.
It might have the same name as the referenced one but different version, >culture or public key token.
I know there are tons of these posts on SO and all over the web, but I have one question to which I have not been able to find an answer. Where else, other than web.config, does an ASP.NET get these version numbers from? In the references section of my app, the version is listed as 9.0.0.0. However, when I compile the app and put into IIS, I'm getting exceptions for the wrong version number.
I have already tried:
recompiling the app,
restarting the server,
restarting IIS,
clearing the ASP.NET temp files
restarting the app pool,
putting a newly recompiled version of the app onto the server,
checking the web.config (I can't even find some of these dlls referenced at all in the web.config file)
checking the packages.config file (it's not in here either)
Are there any other spots where these references are stored? I know that in visual studio I can expand references, but I'm assuming that list is stored in a file somewhere and I'm wondering where that file might be?
Where does my app get the idea that it needs version 11.0.0.0 of the assembly when it's listed as 9.0.0.0 in references?

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

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.
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".
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.
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.
Asp.net loads all dlls in the bin directory.

WCF service in a precompiled web application - Could not load file or assembly

I have a solution which contains multiple WAPs (Web Application projects).
Every WAP has it's own Web Deploy project in order to be able to precompile these sites.
On one of the web app we are created a new WCF file with
AspNetCompatibilityRequirementsMode.Allowed
In debug mode it is working ok, but if i switch to release it crashes:
(we are using msbuild to create the deployable versions)
Could not load file or assembly 'App_Web_*****, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null' or one of its dependencies. The
system cannot find the file specified.
I found some explanation in this link: WCF service
WCF stores the list of referenced assemblies into the customString
attribute in the build result (service.svc.cdcab7d2.compiled),
including App_Global. It seems there is an incorrect assumption here
that those assemblies will always be there, which is not necessarily
the case in Web Deployment Projects (aspnet_merge) where assemblies
will be merged. After the merge step, the assemblies are actually all
merged into a single assembly (let us say MyWebSite.dll) as we
selected that option in WDP. ASP.NET only updates the .compiled files
it knows about, so App_Global.asax.compiled actually has a correct
reference to MyWebSite_Deploy.dll instead of App_Global.dll. Original
assemblies are removed after the merge step. WCF reads the list of
assemblies previously stored, and throws when it cannot find
App_Global
List of solutions i've tried:
1.Check 'Allow this precompiled site to be updatable' - not worked
2.Remove manualy the App_* reference from service.compile file
(It worked but it should be another solution)
3.Add fully qualified name for the service/factory in .svc
The service has a fully qualified name.
4.tried to set this key:
<SourceWebPhysicalPath>..\..\ProjectName</SourceWebPhysicalPath>
following these instructions
5.<compilation debug="false" batch="false">
Tried this to set to web.config using these instructions
6."Merge All outputs to a single assembly"
i haven't tried this because it requires to register all the used assemblies to GAC and means we need to change the deployment logic.
I don't want to delete the asp.net temporary folder because it stops the application and it is inacceptable
I also found Scott Gutthrie link but it's from '07 it should made it's way to asp.net 4.0
Additional Info
The service is placed: ProjectName\WebResorce\Service.svc ,
<%# ServiceHost ... Factory="SolutionName.SharedWeb.WadoLabsServiceHostFactory" %>
where the SharedWeb is a Shared Web project
Do you have any other ideas?
Thanks in advance
The following setup worked for me:
In the svc file, specify a qualified name of the service, as <%# ServiceHost ... Service="<Namespace>.<ServiceContractClass>, <AssemblyName>" CodeBehind="ServiceContractClass.svc.vb" %>
(Can't remember why it was required, but) I made sure that the Namespace and the AssemblyName are different.
The trick is to specify the qualified name, including the AsseblyName.(The assembly name that is specified in the project containing the service, not the Web Deploy Project).
Also note that there is a space between the comma after the class name, and the AssemblyName.
Why don't you implement the WCF services in a separate library project inside the same solution, and simply reference that project from your web app(s)? That way they would stay out of the pre-compilation process, and you could work with predictable type names inside the *.svc files. Plus, this would probably also give you a cleaner solution structure.

Where are Web Application Project Assembly references stored?

Where are assembly refernces stored for a web application?
In a Web Site, I see assembly tags written to the assembly node in the web.config when you add a reference. I am just curious as to how the Web Application Project makes the connection to get the correct local dll?
I manually add the reference and the application builds, but the dll is not imported into the BIN folder, and the assembly nodes are not created in the web config as they are in a Web Site. I do a solution search for the text 'assembly="SomeAssembly..." and no results are found.
I am just curious as I am trying to centralize updating assembly references as a 3rd party control vendor puts out hotfixes on a regular basis and we end up having to run around and update all the individual page refernces to the assembly. I was able to do this effectively in the Web Site project, but I am fairly new to Web Application Projects. Any advice or links would be appreciated. I guess I'm looking for tips on assembly & control reference management for ASP.NET Web Application Projects.
Like most Visual Studio projects, references are kept in the project.
There are two kinds of reference:
Project References are references to another project in the same solution. They look like this:
<ProjectReference Include="..\VBClassLibrary1\VBClassLibrary1.vbproj">
<Project>{045D7D9F-8E44-4C4B-95F8-620E86593C5B}</Project>
<Name>VBClassLibrary1</Name>
</ProjectReference>
File references are references to an arbitrary file on disk:
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
If you expand the References folder and click on a reference, then look in the Properties window, you'll see that both kinds of reference have a "Copy Local" property. For project references it defaults to true, for file references to false (though maybe that's only if the file is in the GAC). Changing the default adds:
<Private>False</Private>
Since the assembly was not imported to the BIN folder, and your application works, I assume that it is stored in the GAC (global assembly cache) and marked as "copy local=false" in the reference properties. You don't see the reference to the assembly in the web.config, since your code behind assembly - YourApp.dll (which is always created for web-applications), contains a standard assembly reference to that assembly. When you run your application it loads the assembly from the GAC.
Those "missing" dlls are probably in the Global Assembly Cache and are available to all .NET applications.
You can add control references to the pages/controls section of web.config, which will apply to all pages in the application.
I had the same issue, deleting .vs folder in the directory of the project solved the issue for me as it forced the recreation of .suo file which (though bite code) had reference to the web.config file in the wrong directory

Resources