ASP.NET 5 Reference Class Library With Nuget Packages Fails During Publish - c#

Thanks in advance for your help, I appreciate it!
I am looking for some direction on successfully referencing a normal (Non-ASP NET) Class Library FROM an ASP.NET 5 project and have it successfully publish. The catch is that the Class Library uses references to packages brought in from Nuget.
Here are the details and how to reproduce:
New ASP.NET 5 Solution and Website.
Change reference to dnx46
Remove dnxcore.
Add a new Class Library and target .NET 4.6.
Add a nuget package to the Class Library (For Example, add EntityFramework 6.1.3)
Issue Command "dnu wrap .
Add the dependency to the the web project.json:
"frameworks": {
"dnx46": {
"dependencies": {
"ClassLibrary": "1.0.0-*"
}
}
}
At this point, we have the "ClassLibrary" "wrapped" in the "wrap" folder.
The solution and project starts up without an issue, all dependencies are found and resolved. Everything compiles and it runs on IIS Express without issue.
Now if you try and perform a "Local Publish" to deploy to IIS, it will complain that the reference to "EntityFramework 6.1.3" found within the "wrap" project.json cannot be resolved.
After trying this out multiple ways, I think it's because the "EntityFramework" DLL from the nuget packages folder never officially gets wrapped. Somehow this doesn't cause an issue when running on IIS Express but causes an issue when publishing. Although I've used "EntityFramework" as an example, you could have used any reference from Nuget.
Has anyone experienced this before, and if so, how did you resolve it?

Related

could not load file or assembly exception NET 5/6 of NuGet package for NET Standard

I'm at the end of my rope trying to figure out why my working DLL cannot load a NuGet package that it could always load before (like for a whole year). My system has 70 NET 6 projects and half a dozen of them use the same NuGet package to read XML files. Recently (a few months ago) I upgraded everything to NET 6, and even after that upgrade, everything worked fine.
But now, one of my C# class libraries generates an exception in a constructor because it can't find the NuGet package that sits right beside it in the filesystem app folder where everything is loaded from. The error message was:
.ctor Could not load file or assembly xxx blah blah. The system could not find the file specified.
For what it is worth, here is a trace of the build options in the batch file that I have been using for months.
Deleting hscore\hscore\bin Deleting hscore\hscore\obj Deleting
hscore\hscore\packages "C:\Program Files\Microsoft Visual
Studio\2022\Community\MSBuild\Current\Bin\msbuild.exe" -nologo -m
-V:minimal -t:clean;restore;publish /p:Platform=AnyCPU /p:PlatformTarget=AnyCPU /p:Configuration=Debug
/p:TargetFramework=net6.0-windows7.0 /p:RuntimeIdentifier=win-x64
/p:SelfContained=false /p:PublishProtcol=FileSystem
/p:DeleteExistingFiles=true /p:PublishDir=c:\dev\holding\core.plt
-nowarn:MSB3305 c:\dev\products\hscore\hscore\hscore.csproj
Determining projects to restore... Restored
c:\dev\products\hscore\hscore\hscore.csproj (in 874 ms).
hscore -> c:\dev\products\hscore\hscore\bin\Debug\net6.0-windows7.0\win-x64\hscore.dll
hscore -> c:\dev\holding\core.plt\
I have done the following to debug it, without success:
deleted the bin/obj folders of the failing class library
checked the target framework of all projects (= net6.0-windows7.0)
checked the runtime identifier of all projects (= win-x64)
checked the build configuration (Debug, AnyCPU)
removed and re-added the NuGet package (with a specific version)
the Nuget package depends on NET Standard, compatible with NET 6
and I use the same version in other NET 6 programs that are working fine
restored and rebuilt the DLL
published it to the destination folder where it is run from
checked that the expected Nuget package is there (it was)
and yet it still fails to find the Nuget package
I tried to trace DLL loads of the process with the SysInternals Process Monitor, but I am not good enough to do that (if it is even possible). I can filter events to see the parent app process load, but the failing DLL is called by the parent process and I don't know how to see the search paths it is using to find the Nuget package.
I want to believe that the problem is a version mismatch between NET 5 and NET 6 and the version of the Nuget package sitting in the folder, because I once had a problem like that. For example, if I had a NET Framework version of the Nuget package, it would not be "found" by a NET 5 DLL that wanted to load it. (I am NOT saying that is my problem, because I have no NET Framework projects anymore.)
The most recent thing I have been working on is the build system and options. I can build the whole system with batch files or with parallel builds (when the system is working). I use the same msbuild options in both cases, and the batch method has been reliable and shows no build errors, no publish errors, all the correct build options, and no warnings or errors whatsoever.
The Nuget package pulls in 10 or 20 dependencies, but that is all automatic, and the package works with other console programs and apps that are working fine. So, I don't think there is anything wrong with Nuget package. All the working apps use the same Nuget package from the same runtime folder. I don't know why this one DLL is having a problem. AND I have not changed anything in the failing DLL class library for months (and it has been working fine).
Does anyone have suggestions on what else I might try to debug the problem and get the system working again? Thank you.
UPDATE - New version and build, but still a runtime failure.
Just to be sure, I upgraded the Nuget package that could not be found to the latest version and replaced all references in my 70 projects to the new version. Then I rebuilt the system (no warnings, no errors). But that did not make a difference. Now the new version cannot be found.
All unit tests of the code in question work flawlessly in VStudio, presumably because VS loads the Nuget package properly. I am mystified and would appreciate thoughts on how to proceed. Thank you.
UPDATE 2 - installed 'dotnet-trace' and traced DLL loads
I found a page that described how to dotnet tool install --global dotnet-trace and then captured a trace of my app trying to find the elusive Nuget package that is sitting right beside the requesting DLL. Although I could my app loading various app DLLs (and tons of system DLLs) with found pathnames, the trace showed nothing useful about the Nuget package.
The trace entries show the system searching in stages FindInLoadContext, then ApplicationAssemblies, then AppDomainAssemblyResolveEvent. After that, the system throws an exception because it can't find the Nuget package.
I would have thought the system FindInLoadContext would find it in the same folder as the executing and requesting assemblies, but it seems not so.
Ideas? I'm lost. And everything used to work fine.
UPDATE 3 - A small console app calls the DLL and it finds the Nuget package
The problem scenario in this question is: WindowsFormsApp -> loads MyCore.dll and calls new MyCore.MyObject(), which in the constructor tries to read some XML files using MyUtils.dll, which tries to reference the mystery Nuget package for reading XML files. MyUtils.dll cannot find the package, no matter what I do.
I wrote a small console program to load MyUtils.dll and called the exact same MyUtils.ReadMyXmlFiles API to read the files. The console app (actually, the system assembly loader) correctly found the Nuget package and read the XML files properly. This all occurred in the same folder that contains the Forms app and the Nuget package.
The only difference now is that the WindowsForms app calls an intermediate DLL that calls a constructor that references MyUtils.dll.
Could the intermediate DLL + constructor call be changing the Assembly Load Context (FindInLoadContext search rules) for the Nuget package load operation? Very strange.
The overall problem was that my Windows Forms app failed during boot (in the Form_Load event) because a Nuget package could not be found to read some XML configuration files.
Four assemblies were involved in the problem. Assembly1 (the app) called Assembly2 (.. new Assembly2Object()), whose constructor called an Assembly3 method (utilities.ReadXMLFile) which called Assembly4 (NugetPackage.XMLReader).
You can see that only Assembly4 references the Nugetpackage which could not be found. Normally, there should be no reason for Assemblies 1 or 2 to know about the existence of the NugetXmlReader used by Assembly3. But, the exceptions and assembly load traces of dotnet-trace and procmon clearly showed that Assembly3 (utilities.ReadXmlFile) could not find the NugetPackage at runtime, even though the right package was in the folder beside the executing assemblies (1->3).
The "solution" for my case was to add a Nuget package dependency to
Assembly1 (the WinFormsApp). As soon as I did that, Assembly3 (utilities.ReadXmlFile) could find Assembly4 (Nugetpackage).
My working theory is that during a WinForms boot sequence (including the Form_Shown event), the AssemblyLoadContext from Assembly1 is used to look up all assemblies in any call chain (like Assembly2 calling Assembly3 calling NugetPackage4).
Because the load context of Assembly1 has no reference to NugetPackage, and because the .deps.json file for Assembly1 is present (the doc says it is used to form the load context), Assembly3 - using the assembly load context for Assembly1 - could not find the NugetPackage.
When I added a dependency to Assembly4 (Nugetpackage) to Assembly1, then the assembly load context from Assembly1 was used by the System AssemblyLoader FindInLoadContext phase to search for (and find) the NugetPackage4 wanted by (the referencing assembly) Assembly3.
I used to think that each assembly in a calling chain would have its own assembly load context used by AssemblyLoad/FindInLoadContext. But I think that no longer. At least for my case of a Windows Forms app booting up, the assembly load context from the top-level app is being used to look up Nuget packages far down the calling chain.
It's worth repeating that my little test console apps always found the Nuget package without adding the package as a dependency to the top-level console program. I wrote console programs to test the calling chain from the bottom up: Test1) console calls Nuget directly - found; Test2) console (w/o Nuget dependency) calls Assembly3 - Nuget found; (Test3) console (w/o Nuget dependency) calls Assembly2 - Nuget found.
Then I wrote a skeleton WindowsFormsTestApp to call Assembly2 (just like the console program did) - Nuget NOT found. When I added a Nuget dependency to the WindowsFormsTestApp - Nuget was found by Assembly3.
The final step was to add a Nuget package dependency to the WinFormsApp that started this whole mess. Presto! Assembly3 found the Nuget package immediately.
My (unproven) belief is that somewhere along the line of upgrades from NET 5 - NET 6 (several SDK versions of each one), the assembly load context rules changed somehow. I could be wrong, but I lean toward this belief because my code from App->Assembly2->Assembly3->Nuget did not change during several months of successful operation. And just a couple of weeks ago after another NET 6 SDK upgrade, things broke.
Hopefully, this record might help someone someday. It seems completely unintuitive to me to add a Nuget package dependency to the top-level Forms app to help Assembly3 find a Nuget package sitting in the same folder as all the other assemblies.
After all this, I am coming around to the idea that the top-level app must/should include dependencies on anything the app ever calls, including packages used by dependent assemblies. (Although I am still puzzled as to why the code worked for months before without the Nuget package dependency.)

Microsoft libraries missing when compiling .NET5 project

I'm trying to decompile ASP.NET Core WebApi project and gather all methods from all controllers. When my project targeted .NETCore3.1 it worked by running this code:
Assembly assembly = Assembly.LoadFrom(assemblyPath); // assemblyPath pointed to .dll
var types = assembly.GetExportedTypes();
But after updating to .NET5, the second line (assembly.GetExportedTypes()) from above throws an exception that file Microsoft.AspNetCore.Mvc.Core.dll is missing. When I copied that file manually from an old project (compiled as .NETCore3.1), it worked!
On the top of that, when project is more complicated, has EFCore dependency and more... more files are missing when compiling the project under .NET5. These are:
Microsoft.Extensions.Hosting.Abstractions.dll
Microsoft.AspNetCore.Mvc.Abstractions.dll
Microsoft.AspNetCore.Authentication.Abstractions.dll
I have two questions:
Why these files are not copied to the output folder?
How can I properly read all endpoints/methods in Controllers having complied binaries of the ASP.NET WebApi? Am I doing something wrong?
Steps to reproduce:
Create ASP.NET Core WebApi project targeting .NET5.
Create other project that targets .NET5 and implement these two lines:
var assemblyPath = "C:\\Projects\\Other\\DotNet5Test\\DotNet5Test\\DotNet5Test.WebApi\\bin\\Debug\\net5.0\\DotNet5Test.WebApi.dll";
Assembly assembly = Assembly.LoadFrom(assemblyPath);
var types = assembly.GetExportedTypes();
Run it
EDIT:
I tried adding Microsoft.AspNetCore.Mvc.Core from nuget, but Microsoft.AspNetCore.Mvc.Core.dll is not being added to the output folder
I've had similar issues sporadically with various projects in the past. The most reliable solution for me has been to install any problematic libraries through the nuget packet manager. Remove any dependency files you manually added before doing this.
I think the issue is that Microsoft.AspNetCore.Mvc.Core.dll ships as part of the framework-dependent deployment (FDD) rather than self-contained deployment (SCD) see the accepted answer Is there any GAC equivalent for .NET Core?.
Given I saw this question of yours posted earlier, How to retrieve Controller methods from WebApi binaries? I have a feeling you are trying to execute the code from a wpf application targeting .net 5 but the app is not able to use FDD to resolve the assembly.
The answer may be that you need to change your webapi app to use an SCD deployment model, but not having used SCD for web apps perhaps google will help.

Using .net standard 1.5 lib in .net 4.6.2 misses System.Runtime 4.1.0.0

I've some problem when using .net standard in .net framework 4.6.2 consoleapps.
I could reduce the problem to this:
Given:
I create a .net standard 1.5 client library vis vs 2017 with this single class
public class Class1
{
public List<int> Get()
{
return new List<int>() { 1, 2, 3, 4, 5, 65, 6 };
}
}
Now I create a new .net 4.6.2 console application which is just calling the method of this class:
static void Main(string[] args)
{
var foo = new Class1();
Console.WriteLine("Done!");
Console.ReadLine();
}
Now I get
System.IO.FileNotFoundException: 'The File or Assembly
"System.Runtime, Version=4.1.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a was not found
When I add the .net standardlib nuget package to the .net fx console it works. but then the system.runtime would be aviable via GAC and via nuget reference which seems to be quite ugly for me.
I pushed this short test solution here: https://github.com/Gentlehag/NetStandardSample
What am I missing?
I've added a repo that shows you how to do this. From the README.md:
Requirements
Generally speaking, using libraries targeting .NET Standard in an application
targeting .NET Framework requires the application project to include a NuGet
reference for .NET Standard (NETStandard.Library). This ensures that the right
set of assemblies are included with the application.
In Visual Studio 2015, the default way of consuming NuGet packages from .NET
Framework projects is via packages.config. I don't recommend this path as
this means that all assemblies are directly injected into the application
project, which will significantly bloat your project file. Instead, I recommend
you use project.json. To do this, perform the following steps:
Uninstall all packages (if you're still using packages.config)
Delete the empty packages.config
Add project.json file with this content:
json
{
"dependencies": {
"NETStandard.Library": "1.6.0"
},
"runtimes": {
"win": {}
},
"frameworks": {
"net462": {}
}
}
Please note that you can generally depend on the latest version of the
NETStandard.Library package, but you need to make sure to keep the framework
moniker in sync with the version of .NET Framework your app is targeting, i.e.
when you're targeting .NET Framework 4.6.1, you need to make sure to use
net461 instead.
This feels clumsy
Yes it is. We're planning on addressing this in two ways:
We're replacing project.json with an MSBuild based solution in Visual
Studio 2017. You'll still need to add the reference to NETStandard.Library, but
you no longer have to mess with the way packages are being represented nor
having to manually keep targeting information in sync.
We're planning to update .NET Framework so that future version of it come with
built-in support for .NET Standard, in which case the reference will no longer
be needed.
I found that adding the NETStandard.Library did not work for me, but ensuring that binding redirects were generated on build did the trick. For that you should ensure that you have
<PropertyGroup>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
somewhere in your project file. This should work for console or web apps. If you're having problems running unit tests, you can use this:
<PropertyGroup>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>
The GenerateBindingRedirectsOutputType is necessary as the unit tests are contained in a class library which doesn't have executable output by default, so this forces any redirect configuration to be written into the build artifacts, ready to be used when the tests are executing.
You can find more details of the issues involved here: https://github.com/dotnet/announcements/issues/31

Referencing a .net 4.6. csproj in asp .net 5 class .xproj issue

I have a. net 4.6 class library with the wrap folder configuration which includes the project.json which is configured to point to the compiled bin/obj/[output] .dll and .pdb files and the global.json in the .csproj root.
This was configured automatically via adding the .csproj reference in the asp. net 5 class project.
However the local package folder in c:\user\\.dnx\packages is not being created thus the output states:
the package could not be found
I am using the beta7 release version of dnx.
Things I have tried
I have tried running dnu restore from the command line with the same output result.
I have updated to the latest beta 7 web tool for vs 2015 and updated to the latest dnvm.
I was able to solve my issue by manually adding the reference to the wrapped csproj into the global.json of the .xproj.
I also posted this finding into the git issue listed in the comment in the op.
{
"projects": [ "src", "test","wrap","../hldotnet_lib_hlenums/wrap" ],
"sdk": {
"version": "1.0.0-beta7",
"runtime": "clr",
"architecture": "x86"
}
}
Update
Nevermind it still is having issues resolving dependencies, using a workaround by generating nuget packages of the projects and reference them that way for now.

The type or namespace IAppBuilder could not be found(missing using a directive pr an assembly reference)

I am working on an Asp.Net MVC 4 Application in which I am using SignalR 2.0.1 and I Mapped it using Owin Startup class and it worked fine at first.
All of a sudden when I tried to rebuild my app it said that the type are namespace IAppbuilder could not be found.
Following is my start up class
using Microsoft.Owin;
using Owin;
using WhiteBoardApp;
namespace WhiteBoardApp
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
I have installed Owin package too, and for some reasons I could not find Owin Startup class so I just added a normal class and included all the references that are needed.
May I know where I am making a mistake
Try to use Package Manage Console and do
Update-Package Owin -Reinstall
I was having similar issue. But instead Owin, problem was causing Microsoft.Owin, obviously
Update-Package Owin -Reinstall
Didn't work, neither did Update-Package Owin
BUT
Install-Package Microsoft.Owin
did work fine for me, thanks.
The IAppBuilder interface is found under Owin package. Just add a reference in your class file:
using Owin;
And rebuild. Your project will pick this up.
I have no idea why VS didn't pick this up, but it didn't. Once I added this reference to my project, then everything fell into place.
I encountered the same problem while building my project. Here are the steps that helped fix my problem:
Go to Solution Explorer and look for your project
Under your project, expand the References; You should see warnings on the problematic reference
Right click References and open Manage NuGet Packages
Search the name of problematic reference i.e. Microsoft.Owin; After loading it shows that it is already installed (It is, but it installed incorrectly. Checking the properties > version at step 2 shows 0.0.0.0)
Check Force uninstall, even if there are dependencies on it
Uninstall
Install
Build and run the project
Problems
Cannot install Microsoft.Web.Infrastructure because it already exists in the packages folder. Rolling back...
Go to your project folder and look for packages
Find the problematic package i.e. Microsoft.Web.Infrastructure
Delete the folder
Resume from step 7
Alternatives
Here are the alternatives I've read about to fix this kind of problem.
Clean and Rebuild Project / Solution
Restart Visual Studio
Restart PC
Good luck.
My Visual Studio 2013 for some reason didn't realize that the references paths existed. The yellow exclamation mark in front of the references was shown for all the added packages. I checked ../packages/ but all files existed, i also opened the .csproj file which referenced the correct paths.
Closing and opening the solution returned quite a lot of errors, and could not load the projects included in the solution.
Restarting Visual Studio 2013 saved the day for some unexplained reason.
My following using's equivalent in F# present a problem of hiding the IAppBuilder. It turns out that the Owin stipulation was being interpreted as an incomplete System.Web.Http.Owin reference, even though the Owin.dll providing the Owin namespace was referenced.
open System.Net.Http
open System.Web.Http
open Microsoft.Owin
open Owin
The problem was resolved by rearranging the usings as follows:
open Microsoft.Owin
open Owin
open System.Net.Http
open System.Web.Http
...granted, this may be a bug peculiar to the F# compiler and name conflicts are handle better in C# and elsewhere.
In my case, I had moved around the project folders and the location of the vs solution file (.sln). Once I was done with re-adding the projects, there was a packages folder on the solution level and one was left in a project sub folder.
This way, in that project, the relative package folder links in the .csproj file got messed up.
The reinstallation or other tips regarding the nuget package manager in this thread were helpful. I noticed, that after I reinstalled a few packages, in my git source code diff, the path of the packages folder was changed within the csproj file.
Before
<HintPath>packages\Microsoft.Owin.4.0.1\lib\net45\Microsoft.Owin.dll</HintPath>
After
<HintPath>..\packages\Microsoft.Owin.4.0.1\lib\net45\Microsoft.Owin.dll</HintPath>
So, if you run in the same issue and you have a lot of nuget packages, it might be easier to close the whole solution, open the csproj file(s) in a text editor like vscode and fix the relative links with search and replace. Then just save, close, reopen solution in VS and restore nuget packages. That should do the trick.
(In any case, you should delete the local packages folder on the project level, so that the project really fails, if it does not get the right packages.)
It's an ordering issue.
using Microsoft.Owin;
using Owin;
Leads to Microsoft.Owin to be defined first, then Owin is found under already imported Microsoft namespace. If you mouse over Owin of using Owin you should see it was resolved to Microsoft.Owin again and furthermore IDE will gray out using Owin as redundant unused reference.
Do:
using global::Owin;
Which clarifies for the compiler not to look for Owin under already defined namespaces (e.g. Microsoft. namespace).
http://www.asp.net/signalr/overview/getting-started/tutorial-getting-started-with-signalr
Check for the visual studio you are using
You can find the following comment
Note: If you are using Visual Studio 2012, the SignalR Hub Class (v2) template will not be available. You can add a plain Class called ChatHub instead.
Also
Note: If you are using Visual Studio 2012, the OWIN Startup Class template will not be available. You can add a plain Class called Startup instead.

Categories

Resources