Project reference VS NuGet - visual-studio

How should I reference to another project A from project B in the same solution?
What do I gain and what do I lose if I:
Add the reference to project A as a project reference.
Install the NuGet package of project A in project B.
Things that would bother me are build dependencies, versioning..?
Or does this totally destroy the purpose of a solution?

Project reference VS NuGet
Project reference or NuGet is a very common problem in our development process, we need to choose which one to use based on our actual situation.
For example, if the referenced project A is modified frequently during the development process, we recommend to use Project reference. Because if you use nuget, you have to rebuild the referenced project, recreate the nuget package, reinstall that nuget package to the project B, even you have to publish it to the server. This will bring a lot of unnecessary work and we often forget to update our nuget package after we modify the referenced project A. If you use the project reference, you will not have these problems. The modified referenced project A will be update automatically before we build the project B.
On the other hand, when we share our referenced project A out of solution, or share that project to others, nuget will be a better choice. It has more portability.
So the project reference will be recommended when you reference to another project A from project B in the same solution, the nuget is more appropriate when share the reference project out of solution or share project to others.
Besides, there is a Visual Studio extension NuGet Reference Switcher, which which automatically switches NuGet assembly references to project references and vice-versa.
Hope this helps.

With the first approach, you gain in simplicity, since you don't need to generate a new version of the ProjectA nuget package, every change you make in it (i.e. ProjectA.nupkg).
However, with the second approach, you gain in portability, since you can easily share the same nuget package with other projects / solutions.
Personally, I create nuget packages only for projects whose goal is to share with other solutions. (E.g. libs and frameworks).
Hope this helps you decide!

Nowadays with the new csproj format the you can use both at the same time (if you have both projects in the same solution).
In your example, you could reference project A from project B as a project reference. Then, if you want to release project A as a NuGet package you just need to add the following tag to it's csproj inside a PropertyGroup:
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
The plot twist: If you want to release project B as a NuGet Package too just add the GeneratePackageOnBuild target - MSBuild will set projectA.nupkg as a dependency in projectB.nupkg.
This way you can work internally with your projects while at the same time release them as packages to third parties or other teams.

You could use both: project references during development (faster), and package references during production.
In your .csproj project file:
<ItemGroup Condition="'$(Configuration)'=='Debug'">
<ProjectReference Include="../../../Library1/Library1.csproj" />
<ProjectReference Include="../../../Library2/Library2.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)'!='Debug'">
<PackageReference Include="Library1" Version="1.0.0" />
<PackageReference Include="Library2" Version="1.0.0" />
</ItemGroup>
In development: project compiled in debug mode, so the project reference will be used.
In production (CI server, docker container): project compiled in release mode, so the package reference will be used.

Related

Is there a way to configure project paths outside of the solution file in Visual Studio 2019?

I have a Visual Studio solution with the project I am working on (main project). The solution references a different project that main project requires as a dependency (dependency project).
The solution and the main project are located in one directory:
/mycode/main_project/main_project.sln
/mycode/main_project/main_project.csproj
The dependency project is located in a different directory:
/mycode/dependency_project/dependency_project.csproj
Both of these projects are under source control. I want to create some kind of configuration file for main project that is not under source control, so that another developer could clone both projects wherever they want and simply edit a non-source-controlled configuration file to allow the main project's solution to locate dependency project.
Currently, main solution locates dependency project using a relative path:
../dependency_project/dependency_project.csproj
If I enforce that all developers should clone these two projects to the same directory, the main solution will successfully link to the dependency project and everything will be happy. However, I would prefer that another developer can place the dependency project wherever they want.
Does Visual Studio 2019 Community support any kind of solution configuration file which could be kept ignored by version control and used to resolve the path to the dependency project?
Solution files are very primitive and do not offer such a dynamic functionality. However, if you don't need dependency_project to show up in the IDE, you can still reference it from main_project.csproj and that does give you more options. It should still build fine even if the project doesn't show up in Solution Explorer.
For example, you could reference it through an environment variable, with a default expected path if that variable isn't set:
<PropertyGroup>
<DependencyProjectPath Condition=" '$(DependencyProjectPath)' == ''>../dependency_project/dependency_project.csproj</DependencyProjectPath>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(DependencyProjectPath)" />
</ItemGroup>
If you set the DependencyProjectPath environment variable before opening the solution (because VS inherits the environment variables from where it was launched), it will override the default setting here (based on the Condition attribute).

Package dependency ignored by Visual Studio 2019

Context
There are two .NET Core 3.1 projects a Visual Studio 2019 16.7.2 solution.
The class lib project has a package dependency on NuGet package AutoMapper 9.0.0
The web application project has a project dependency on the class lib.
Runtime I got the "Could not load assembly AutoMapper 9.0.0.0". My first thought was some version mismatch but all projects set to .NET Core 3.1.
I've investigated, and in the web application project /bin folder there is no AutoMapper assembly.
So I've investigated further, and it seems the web app project somehow ignores this implicit dependency, see picture.
What I've tried so far:
I've tried to clean all, then rebuild.
I've tried to exit, then restart Visual Studio
Question
What am I missing here?
For Kirk's comment:
<ItemGroup>
<ProjectReference Include="..\Benedetto.Abstractions\Benedetto.Abstractions.csproj" />
<PackageReference Include="AutoMapper" Version="9.0.0" />
<PackageReference Include="IdentityModel.AspNetCore.OAuth2Introspection" Version="4.0.1" />
First, Glad to know that you have solved the issue. To add an answer here for other community members handle similar issues.
Solution
clean all nuget caches first or just delete all nuget caches under C:\Users\xxx(current user)\.nuget\packages
close VS Instance, delete bin and obj folder
use nuget xxx\xxx.sln command line to restore nuget packages
then restart project to fix the issue.

Nuget packages with both debug and release

In our work we have one team that develops libraries and other teams that develop projects using those libraries.
The libraries team has much more experience than the projects one.
We created this environment here:
All the libraries are in nuget packages, in a nuget server, in azure devops.
We have source link in Azure devops.
But when we deploy the libraries, we have to choose between debug or release, and we have the pros and cons of each.
My ideal nuget package would have both debug and release, and would select the same as the project running it.
this way I would have better debugging for the projects team, and maximum performance on the releases.
I talked with https://twitter.com/rrelyea and he gave some ideas, but they seem to complicated for the other teams to implement, or complex do manage.
Like 2 nuget servers, one for debug, and one for release, and configure those different ones on the machines and on the build server.
Or 2 nuget packages, with .debug and .release on the name of the package, and configure the project to load a diffent one on each mode.
The real problem is that I need a guarantee that all the packages have the same id and version on both servers.
Isn't there a more automatic way to pack the packages?
Simple if it's debug use the debug, if it's the release use the release.
By the way, how much performance difference is between debug and release in this case?
Isn't there a more automatic way to pack the packages?
Actually, nuget package does not have a mechanism to let a project to reference the debug output files or release output files based on the configuration of the main project.
And when you pack a project, it does not have a function to include the Debug or Release output files at the same time and then let the main project-------when using Debug, reference the Debug content of the nuget, when using Release, reference the Release content of the nuget.
So far, nuget is not yet so flexible, and it can't do the functions you mentioned above.
=====================
As a suggestion, you should create two nuget packages(Debug or Release) of the project and then manually install the corresponding package as required.
You can create a net standard library project, and add these in xxx.csproj file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>PackageName</RootNamespace>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<PackageId>PackageName_Debug</PackageId> //name the nuget package which contains Debug key name
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<PackageId>PackageName_Release</PackageId> //name the nuget package which contains Debug key name
</PropertyGroup>
<PropertyGroup>
<Version>1.0.0</Version>
<Authors>your_name</Authors>
<Company>your_company</Company>
</PropertyGroup>
<ItemGroup Condition="'$(Configuration)'=='Debug'">
<None Include="$(ProjectDir)$(OutputPath)$(AssemblyName).pdb" Pack="true" PackagePath="lib\$(TargetFramework)"></None>
<Compile Update="Class1.cs" Pack="true" PackagePath="Resource">
</Compile>
...// add any source files
</ItemGroup>
</Project>
And you can switch the Configuration to Debug or Release to build your project to generate the nupkg file under output folder.
Note:
1) To generate a debug nuget package, you should contains the pdb file and source files into the nuget package and then you can debug it in the main project. There is a similar issue which contains the detailed steps about it.
2) You can define the package_id directly in the new sdk format project. And you should add Debug or Release to distinguish between them.
More info about packing new sdk format project, you can refer to this document.
==============================
In addition, if you still want the initial feature(contain Debug or Release in the same package), you could suggest a feature on our User Voice Forum and I hope the Team will consider you idea carefully and give a satisfactory reply.
Maybe... just add .pdb files from debug folder to Lib using Nuget Explorer

Visual Studio dotnet core copy and paste references

I've known about copy/paste references in Visual Studio since 2010/2012. Has this been updated to work with Core 2?
Here's the SO Question asking about the old style references (before Core, and before the reboot of csproj format): Is it possible to copy / paste References from one project to another in Visual Studio?
Maybe now that dotnet add package is available, we don't need copy/paste references in VS?
"Add Google social login" walkthrough for ASP.NET Core 2.0 suggests using the dotnet CLI to add a package reference:
To install with .NET Core CLI, execute the following in your project
directory:
dotnet add package Microsoft.AspNetCore.Authentication.Google
source: https://learn.microsoft.com/en-us/aspnet/core/security/authentication/social/google-logins?tabs=aspnetcore2x
Writing this answer to my own question so the "just use the CLI" folks have something to upvote.
If you are talking about NuGet package references, don't try to copy the resolved references to dll files manually (the are generated from the obj\project.assets.json file during the design-time build after loading the project).
In the new SDK-based project model and the PackageReference way of referencing NuGet packages (also available for "classic" projects), NuGet references automatically flow transitively across package references. So when your app references a library that uses a NuGet package, you no longer need to install the NuGet package in both the library and the app (and potentially test projects).
Only for "classic" references, this issue remains. However, if you need to import them into all projects (say you got a few .dll files from a 3rd party), you can create a Directory.Build.targets in the solution folder to add them to all projects in your solution (technically, this file is automatically imported into all projects in the directory hierarchy):
<Project>
<ItemGroup>
<Reference Include="AssemblyName">
<HintPath>shared-libs\AssemblyName.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
(you may want to change the reference if you want the "specific version" feature or strong-name references as described in https://stackoverflow.com/a/16580870/784387)

Reference nuget package project from another nuget package project in same solution

I am creating couple of .NET Standard 1.6 libraries that I want to publish as Nuget packages. They share a common libary that is a 3rd project in the same solution as the first two. The shared library has no value by itself, but I am assuming that if I want people to use both of these two libaries in the same project I should publish the shared library as a Nuget package as well. If I don't I am worried about multiple copies of the same shared library "colliding" or not properly warning when there are version mismatch issues.
Am I correct that the shared library needs to be a Nuget package as well? Is there a way to reference the shared library as Nuget package, but use is as if it was a project reference when developing / debugging the 2 main libraries in this solution? If I had to publish to Nuget.org and wait for the package be propagate through the Nuget.org system before using a changed version in a debug session that is REALLY going to slow down development. Note that these are .NET Standard projects. I found How to reference related projects in the same solution when Nuget packages are the required output but that doesn't seem to work with .NET Standard (getting errors during pack) and I am also not sure if .NET Standard not using nuspec files anymore also would cause a problem.
I am also not sure if .NET Standard not using nuspec files anymore also would cause a problem.
The .NET Standard still using .nuspec files, and using old school nuget pack and a .nuspec will resolve this issue.
As per document dotnet pack:
NuGet dependencies of the packed project are added to the .nuspec
file, so they're properly resolved when the package is installed.
Project-to-project references aren't packaged inside the project.
Currently, you must have a package per project if you have
project-to-project dependencies.
So, to include project-to-project references in NuGet packages, you need manually maintain a .nuspec file and add dependencies. You can refer to the Create .NET Standard packages with Visual Studio 2015 for detail info.
Besides, dasMulli has provided a simpler way to do this by involving adding and hooking up a custom target :
<Project>
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);IncludeP2PAssets</TargetsForTfmSpecificBuildOutput>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\testprivatelib\testprivatelib.csproj" PrivateAssets="All" />
</ItemGroup>
<Target Name="IncludeP2PAssets">
<ItemGroup>
<BuildOutputInPackage Include="$(OutputPath)\testprivatelib.dll" />
</ItemGroup>
</Target>
</Project>
The source code comes from: "donet pack" is not including project references

Resources