DNN 7 Web API Module; Could not load file or assembly - c#

Background
I'm building a mobile app for an existing DNN 7 site; made by someone else who left a year ago or so. I had previously set up a WebApi module to handle authentication. Then I had the idea of setting up a class library to hold my DTO objects; since I would have to modify several existing modules to expose web methods and they'd have to interact with my app. So I created a class library threw in two classes and compiled. Added the dll reference to both my app and the web module and they have no issues building when referencing my objects. However, when I send a web request, from either my app or Postman chrome extension, to my module I get:
"Could not load file or assembly 'Elf.Web.Models, Version=1.0.6081.13955, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.",
My app doesn't seem to have issues creating and using the objects, just with the web module.
What I Tried/Checked
Properties I made sure both my class library and my web module were targeting the same framework; .NET Framework 4.5
Reference Property Copy Local is True and per Other Question
I tried manually editing my .csproj file to add the attribute Private to True under my reference. I even tried adding a binding redirect to my assembly.
Manual I also tried opening up my modules install zip tossing the class library dll into the bin folder, re-zip, and then installed to the dnn site. The problem persisted.
If anyone else has an idea of what could be an issue it'd be appreciated.

Putting the library dll in the bin folder of the installer zip file will not automatically put your library dll file into the bin folder of the DotNetNuke installation during install.
Add this to the installer .dnn file under the <components> node.
<component type="Assembly">
<assemblies>
<assembly>
<name>myLibrary.dll</name>
<path>bin</path>
</assembly>
</assemblies>
</component>
If you want the file to be added to the installer zip automatically, you have to make a reference in the ModulePackage.targets file.
<Copy SourceFiles="$(MSBuildDnnBinPath)\myLibrary.dll" DestinationFolder="$(MSBuildProjectDirectory)\Package\bin"/>

Related

.NET cannot locate unmanaged DLL in same directory

I have a C++ DLL library (let's call it unmanaged.dll) that gets wrapped around a managed .NET library (let's call it managed.dll). The managed.dll uses unmanaged.lib to import/link unmanaged.dll. I have another ASP.NET Web API project that uses managed.dll (let's call the project webapi.dll). Now, whenever I build the Web project, in the output directory I get webapi.dll and managed.dll. Then, I manually copy unmanaged.dll to be in the same output folder so that (presumably) .NET can locate it and load it.
However, when I try to run webapi.dll, it fails with an error that it cannot load managed.dll:
Could not load file or assembly 'managed.DLL' or one of its dependencies. The specified module could not be found.
This is particularly weird because unmanaged.dll is in the same folder.
What I find very weird is that if I put unmanaged.dll under C:\Windows\system32 then .NET can properly load it!
My question is how can I make this unmanaged.dll visible to .NET in the folder where the .NET project output is residing?
It's the IIS that is causing the problems. Had the same problem, sovled it by adding the dll to a folder, that lies in the PATH variable.

Do binding redirects in app.config for class libraries do anything?

The VS solutions I often work with consist of a single executable project (console app, web app) and many class library projects that are all referenced by the executable.
When working with NuGet and installing packages, there's often an app.config file created for each project, usually containing nothing else than a list of binding redirects that consolidate versions of referenced assemblies. Sometimes there's some third-party library-specific content (like Entity Framework config section), but let's leave that aside for now.
When I build the solution and use the binaries of the main executable project, I see all the class library project assemblies in the build output together with the corresponding *.config files (the app.config file gets renamed to AssemblyName.config when built).
When launching the main executable, do the config files of the class library assemblies take any effect? Or is it just the app.config file of the executable that has an effect in this case? What if there are some binding redirects set up on some of the class library projects, and some different binding redirects set up on the main executable project — How are these combined, which take priority?
I've tried to research this online and from what I've read, it looks to me like the app.config files for non-executable assemblies are useless (with regards to binding redirects). Can someone confirm this or elaborate a bit more on the topic?
If it is that way, is it actually undesirable to have these app.config files created by NuGet in class libraries if they contain just the binding redirects? It feels to me that NuGet shouldn't create those binding redirects for class library projects, as it will only increase the confusion about what settings are actually applied.
I found these existing Stack Overflow questions on the topic, but their accepted answers are actually contradictory even when they're marked as duplicates of each other.
Why NuGet adds app.config with assemblyBinding to LIBRARY projects during a NuGet package update?
Is the bindingRedirect .config file needed or all assemblies in an application?
The accepted answer to the first question mentions that app.config files are actually used during compile-time, which means they could have effect. Sources like MSDN and MSBuild source code are cited there as a proof it's used during compile-time. Unfortunately, I'm not proficient enough in MSBuild to understand how it's being used, and if it's really a valid argument.
Can anybody describe an example scenario to prove that an app.config with binding redirects for a class library can do anything?
I have multiple applications with similar setup - Web application referencing multiple library projects each having their own nuget packages etc., Based on my personal experience the assembly bindings in the library projects are not considered during run time.
The bindings specified web or app config in the root application (web/console) is that only matters. All my library projects are setup with "Copy to Output Directory" setting as "Do not copy" for the app.config file - that way my output folder is not cluttered with dll and their config files.
Here is the link which says how the assembly is loaded and where is it being searched and the sequence of it. No where in the article they talk about individual project config files.
Hope that helps.
According to this old msdn article:
An application configuration file is an XML file used to control assembly binding. It can redirect an application from using one version of a side-by-side assembly to another version of the same assembly. This is called per-application configuration. An application configuration file applies only to a specific application manifest and dependent assemblies. Isolated components compiled with an embedded [ISOLATIONAWARE_MANIFEST_RESOURCE_ID] manifest require a separate application configuration file. Manifests managed with CreateActCtx require a separate application configuration file.
So only dll's with the ISOLATIONAWARE_MANIFEST_RESOURCE_ID set actually use an independent application config, otherwise it's deferred to the main process config file.
For more info on what ISOLATIONAWARE is you can read this other MSDN article that goes more in depth.
ISOLATIONAWARE_MANIFEST_RESOURCE_ID is used primarily for DLLs. It
should be used if the dll wants private dependencies other than the
process default. For example, if an dll depends on comctl32.dll
version 6.0.0.0. It should have a resource of type RT_MANIFEST, ID
ISOLATIONAWARE_MANIFEST_RESOURCE_ID to depend on comctl32.dll version
6.0.0.0, so that even if the process executable wants comctl32.dll version 5.1, the dll itself will still use the right version of
comctl32.dll.
The answer is maybe. Depending on the type of project the library file is. Some library projects run in contexts where the library's config file is respected (e.g. Azure Web Roles), but that is not the norm.
See my answer here for more details.
Generally there is only one configuration file and thats the configuration file of the executeable (.exe.config, web.config).
Any assembly redirects have to be placed in the configuration file of the executable.
Configuration files of dlls need to be loaded manually using the ConfigurationManager class. See also this question Equivalent to 'app.config' for a library (DLL)
No, only the app.config of the executable will have effect. For example, if you have a console app hosting a WCF service, and in your WCF service you make use of, for example, ConfigurationManager.AppSettings, the AppSettings will come from the console host app.config file. If you spin up another console application (ConsoleClient) to try connecting to the ConsoleHost, then in the parts where the ConsoleClient can be said to be "executing" (for example in its main method), it will use ConsoleClient's app.config, but as soon as it begins using the WCF service, the WCF service will delegate to use ConsoleHost's app.config. (Note that this last point is more relevant to the details behind WCF though.)
Surprisingly, msdn provided this great source:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/e13194df-6308-4cbe-973c-f6a462f43eae/how-can-wcf-library-dll-access-application-settings?referrer=http://social.msdn.microsoft.com/Forums/vstudio/en-US/e13194df-6308-4cbe-973c-f6a462f43eae/how-can-wcf-library-dll-access-application-settings?referrer=http://social.msdn.microsoft.com/Forums/vstudio/en-US/e13194df-6308-4cbe-973c-f6a462f43eae/how-can-wcf-library-dll-access-application-settings?forum=wcf

Microsoft.Owin.Host.SystemWeb dll appearing in deploys

I have a web application which is made up of web forms. Slowly we are converting it over to MVC.
Last week I did a deploy to a testing environment and everything works as expected.
This week I made some changes to some ASPX/code behind files and also some user controls. I did a publish/deploy to testing and I receive an error when I browse to the site through IIS.
The error is:
Could not load file or assembly 'Microsoft.Owin, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e37' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
Comparing the bin folder of the last good deploy, to the broken deploy, the only difference is the broken deploy has one extra file - Microsoft.Owin.Host.SystemWeb.dll
If I remove that file the website is able to load and function correctly.
The website has many projects and references, the root project (the one I right click > publish on) does not have a reference to this Microsoft.Owin.Host.SystemWeb.dll so it must be referenced from another project.
Is there any way to fix this error without having to delete the file from the bin folder? What is causing the error?
Also both bin folders have other Owin dll files.
Microsoft.Owin.dll
Microsoft.Owin.Security.Cookies.dll
Microsoft.Owin.Security.dll
Owin.dll
It sounds like one of your projects use the OWIN middleware. It also seems like someone may have tried to update the package and possibly did not do it properly. I would right-click on the solution and click "Manage NuGet Packages" and re-install the OWIN packages. If that does not work its likely a binding redirect issue that needs to be resolved in the web.config. You may also want to see if there are any OWIN references even being used in the project.

Assemblies/references not found after publication on Azure

I have an MVC5 Web application (VS2012) which has a reference to a WCF Application.
The architecture looks like this:
- Business library
-- References to DAL
- DAL library
- WCF application
-- References to Ressources
-- References to Business
-- References to DAL
- Web application
-- References to WCF application
-- References to Ressources
- AzureCloudService
-- WebRole for Web application
-- WebRole for WCF application
- Ressources
-- References to Business
-- References to DAL
I have created a AzureCloudService with 2 WebRoles for Web and Wcf applications. When I publish the AzureCloudService, no errors are thrown.
But when I go to the Web application on Azure, many references or assemblies are not found. So, I had to add the following line in .csproj file:
<Reference Include="Tools, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL" />
Because the project reference was not enough:
<ProjectReference Include="..\Tools\Tools.csproj">
<Project>{guid}</Project>
<Name>Tools</Name>
</ProjectReference>
But, when I added Wcf application and Ressources references, it asks for Business even if there is no project reference in Web Application. After all, I ended with the following error which makes me feel that I'm doing wrong. Has somebody a hint or advice please?
Couldn't find type for class Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=2.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35.
Of course, the following line is present in the .csproj but doesn't seem to work ... or I don't understand something.
<Reference Include="Microsoft.WindowsAzure.Diagnostics, Version=2.5.0.0, Culture=neutral, PublicKeyToken=somenumber">
<Private>True</Private>
</Reference>
UPDATE:
After some research, I've found out that all the project references in my WebRoles are not included while the Cloud Services publication.
Firstly, I tried to set Copy Local to true (even if they already were).
Secondly, I deleted my WebRoles and recreated them.
Thirdly, I try to add some dummy code to reference the projects indirectly as suggested in this post: MSBuild doesn't copy references (DLL files) if using project dependencies in solution
Then, I tried to add the project dependencies on the Cloud Service Project.
Then, I tried to create a package, rename .cspkg in .zip, unzip it, add the missing dlls to the unzipped WebRole .cssx, and re deploy as suggested in this post: http://blog.toddysm.com/2010/02/windows-azure-deployment-did-you-forget-to-pack-your-dlls.html
I know there are scripts for post build events, but I don't succeeded to create one.
For now, I have to access the Cloud Services VM via Remote Desktop and copy/paste the .dll from my local "/bin" directory to the approot and siteroot "/bin" directories.
However, when an instance is destroyed and recreated due to Azure scalability, the .dll are gone.
So, I'm desperate with these projects dll which are not sent.
Any ideas please?

How can I load assemblies that are placed in the project (portable class library) folder?

I have a .dll file in my project folder and would like to load it via Assembly.Load().
AssemblyName name = new AssemblyName("Portable.Store, Version=0.1.0.0, Culture=neutral, PublicKeyToken=12ay62c33eocf6uf");
Assembly assembly = Assembly.Load(name);
However this would throw a FileNotFoundException due to not specifying a path. And I am unable to use Assembly.LoadFrom() or Assembly.LoadFile() because Portable Class Libraries only support Assembly.Load()
Is there a way to do this inside a pcl? Any help is appreciated, thank you!
Edit #1: Would it matter if the assembly I'm trying to load is a non PCL? I know that this defeats the purpose of the PCL however there are a few libraries that are not included in the PCL. Therefore using conditional compilation, depending on the platform, I will load platform specific assemblies.
Edit #2: Found some more information on where the dll should be placed: https://stackoverflow.com/a/6440406/2464165
As of now I just placed it inside my project folder, with the .sln file and what not Where exactly would be the app probing path?
Edit #3: I was able to get my dll file placed inside the Resources Folder of a .dll file. So I have MyPCL.dll and inside that is where I have the ResourcesFolder/Portable.Store. How could I tell the Assembly.Load to look in specific folders instead of just the main AppX root directory?
I'm making the assumption that you are running the portable library in a Windows Store application (based on the assembly name you are trying to load).
There are two places that store apps find their assemblies, either in GAC if it is a framework assembly or the Appx package if it is a user assembly.
As "Portable.Store" (which I assuming is from my PclContrib project) is a user assembly, it must be loaded from the AppX package. To ensure that both assemblies end up in the AppX package, simply make sure that the Windows Store project containing the AppxManifest references both of them. That's it.
If Assembly.Load still cannot find the assembly, check to make sure that the strong name you are passing to Assembly.Load is correct.

Categories

Resources