How to use different NuGet package versions in different projects? - web-config

I would like to use two different versions of the same nuget package. BUT I would like to use these in separate projects within my solution. I had expected this not to be a problem, but it looks as though (while the NuGet tool is happy to install different versions in different projects) the runtime is not happy to reference them.
To explain, I have projects A and B in my solution. Project A would like to use Acme nuget package version 1.0.0 and project B would like to use Acme nuget package version 2.0.0.
The error I get is this:
Could not load file or assembly 'Acme, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1a2b34567890123' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference.
Of course, project A is referencing the class library project B - I believe that this is, essentially, what is causing the problem.
How can I convince my solution to allow each project to use their desired nuget version?

Related

NuGet: Do Not Set Assembly Reference

I have created a nuget package containing a DLL that I want to share with multiple applications. I want to add this package to applications without setting a reference to the DLL. I am using dependency injection to load this DLL or a test DLL at run-time.
By default, nuget automatically sets a reference to all DLLs contained lib during installation.
Is there any way to configure the nuget package to not set a reference to the DLL when it is installed into my project?
Explicit assembly references. Although if your dll is loaded entirely at runtime (using MEF or Assembly.Load or something similar), then the build system might not copy the dll to the project's output directory. Note these docs are only correct for packages.config projects. I have a PR to improve the docs to explain how to do the equivalent thing for PackageReference.

Get current version of package outside of Visual Studio

We are migrating over to using packages and NuGet for managing our dependencies on 3rd party components. This works well when referencing packages from within Visual Studio or building on the build server via msbuild.
However there are a number of files that we would like to access in our build scripts and installers. Previously these would be in source control with a well known path, now as the version of the package that we are consuming changes so the path to the package and hence the files is changing.
Is there a simple way I can get the path to a given package? The best solution I currently have is to search for all packages.config files and extract the package version from them.
Examples of the files that we need to access are
The NUnit console executable from the NUnit.Runners package for running unit tests.
License files from various packages that we redistribute with our installer.
Using the packages.config file is a pretty good solution. NuGet itself uses two approaches:
Reading the package information from the packages.config and using that to resolve to the packages path.
Enumerating all the directories in the packages directory.
You could use NuGet.Core to do either of the above if you do not want to write the code yourself. The classes that can be used are the DefaultPackagePathResolver, the PackageReferenceFile and LocalPackageRepository or SharedPackageRepository.
One problem with the second approach is that sometimes NuGet may occasionally leave behind NuGet packages that are not necessarily referenced by a project. In that case looking at the package directories may give you the incorrect information.
The only other approach I can think of might be to read the project files looking for the assembly references. Although that would not work for a solution level package such as NUnit.Runners.

Should version numbers in <assemblyBinding > match Nuget version numbers?

Looking at the Web.config runtime section that opens with:
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
follows is a list of depen. Asse. where inside the bindingRedirect the 'newVersion="valu" ' does not always match to what Nuget reports.
Is this something to rectify or ignore?
thx
By NuGet reports I assuming you mean the version number that NuGet shows for a particular NuGet package.
First of all, the NuGet package version does not necessarily match the version of the assembly or assemblies in the package. So the binding redirect version may be different. A good example of this is log4net:
log4net NuGet package version: 2.0.3
log4net assembly version: 1.2.13
So if one of your NuGet packages is referencing an older version of log4net, whilst your project is referencing the latest version, then I would expect a binding redirect to be added which refers to log4net 1.2.13.
NuGet will add binding redirects when a package is installed. You can also manually get NuGet to update the binding redirects for a project by running the Add-BindingRedirect command in the Package Manager Console window.
Add-BindingRedirect MyProjectName
If on rebuilding your entire solution you get a warning that looks like:
MSB3247 - Found conflicts between different versions of the same dependent assembly
Then you should look into fixing the binding redirects or seeing if you can upgrade the older NuGet packages so the conflicts are resolved that way. Otherwise your application may fail to load a particular assembly.
Visual Studio 2013 supports automatic binding redirection for applications that .NET Framework 4.5.1 which is another thing to consider if this applies.

Can a NuGet package declare a dependency without adding that dependency to the project?

I've created a NuGet package that contains some custom MSBuild tasks named MyCompany.MSBuild. These tasks have a dependency on Newtonsoft.Json. This means that after my package is installed in a project, Newtonsoft.Json.dll will have to be in the same directory as MyCompany.MSBuild.dll.
I could easily accomplish this by bundling my own copy of Newtonsoft.Json.dll in my package, but I wonder if there's a better way that means I won't have to update my package whenever a new version of Newtonsoft.Json comes out.
If I declare Newtonsoft.Json as a dependency, NuGet will install that package into the project when somebody installs my package, which isn't what I want to have happen.
How can I specify a dependency in my package without having NuGet install it and add project references? Additionally, how can I copy that package's assembly to my own package's folder after it is installed?
A package with a "hidden" dependency is something absolutely undesiderable in my opinion...
I know it's not a real answer but... Have you considered to use JavascriptSerializer instead of Newtonsoft.Json? It's a bit slower but your package will be absolutely self-contained: less pain for you and for your users.

Varying dependencies depending on target project type

I have a package Ninject.Extensisons.Wcf which shall be installed differently depending on the type of the project to which it is installed. In the case where WCF is hosted in IIS (any project containing global.asax) a second package Ninject.Web.Common needs to be installed together with the package. For all other project types such as libraries, Console, WinForms, WPF applications this package should not be installed.
Is it somehow possible to achieve this e.g., using a powershell script? Or do I have to deploy two different packages in this case?
Unfortunately the current nuspec file does not provide for managing dependencies based on project type. We currently support targeting different framework versions, but that doesn't apply in your situation.
It is recommended that all dependencies are handled using package references. Although it would be technically possible to download and install a package using a PowerShell script, this is not supported and will most likely break in future versions.
First determine if it would actually be a problem to reference a web package in a non-web project. Just because assemblies are referenced, if they are not used, it should not have an impact.
If it turns out that having the web dependency causes undesirable side-effects, then you'll need to create separate packages.
I would split up your package into logical pieces. As you state, you have a package that is used by non-web projects. Web projects require a dependency on a different package.
So now you have 2 logical packages:
MyProject
MyProject.Web
MyProject (dependencies)
SomeOtherPackage
So a user would Install-Package MyProject for non-web projects, and Install-Package MyProject.Web for web projects.
At this point you would be done and everything would be fine. But I think you should consider another step. One of the issues I see with these split packages is that I have to figure out which particular package I need to install. I have to know that I need the "Web" version.
At this point, determine the typical use case for your package. If 90% of your users will be installing the Web version, then I would make a "meta" package that simply has dependencies for your common packages.
In your case I would make 3 packages:
MyProject (meta package)
MyProject.Web
MyProject.Web
MyProject.Core
SomeOtherPackage
MyProject.Core (common non-web package)
By creating the "meta" package, you can reserve the "short" package name for the most common case. This meta package only has dependencies to other packages.
A good example of this is the SignalR package.
Hope this was helpful.