NuGet and multiple solutions - projects-and-solutions

We have two solutions: foo.sln and bar.sln
I have a common library that is used by both foo and bar. Common.csproj is used by both.
If I open foo and update nuget references, all references in Common.csproj point to foo/packages/. If I later open bar and update nuget references, all references get set to those in bar/packages/. Naturally, this pisses off the foo team as it can cause incompatibilities between Common.csproj and Foo-specific stuff like Foo.Data.csproj, which still points to foo/packages.
There must be some obvious solution other than: "create a huge solution that contains all your projects, and if you need to touch nuget, only do it from that solution."
There seems to be an issue on codeplex, (the top voted issue, incidentally), but evidently I'm too thick to understand how this issue is resolved. Can someone explain how to fix this?

This problem preceeds NuGet. If you have a project referenced in two solutions, and change assembly references in the project when it is open in one solution, of course it will change the reference path for that project when it is open in the other solution. This has always been the case, regardless of how the reference was changed (with NuGet or otherwise).
But the real problem is that when you do an update, the updated packages do not appear in the foo/packages directory right?
The simple solution is to move Common.csproj into a solution of its own, with its own references, packages folder, build and release process. Then create a NuGet package of your own with any relevant dependencies built into it. Then you can install your Common package into both Foo and Bar and then the Foo team is free to update to the latest version of Common as and when they are ready.
The main argument that I have heard against this is that you might want to step through the Common code while debugging, but this is no longer an issue with Visual Studio 2010.
The fundamental question you need to ask is who owns Common.csproj? Is it the Foo team or the Bar team?

I fix the problem by changing the hint path in the project fil to contain the $(SolutionDir) variable:
Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)packages\EntityFramework.6.1.3\lib\net40\EntityFramework.dll</HintPath>

Why not have common.csproj as a separate assembly that you reference and has its own dependencies rather than those of the solution its in.
By doing that you protect common from either foo or bar updating the referenced package and breaking it.

In our case, many developers and solutions with tfs, and multiple versions of it in different branches ...
and each developer their understanding of where the source must lie.
Relative path in this case not work, absolute paths in case of coincidence disc are replaced by relative and also did not work.
Our solution consists in getting rid of the relative path.
You can do it if you put NuGetPackages on a separate disk.
like so:
net use /persistent:yes p: \\localhost\C$\NuGetPackagesDiskFolder
Any folder name you wont
After that, you can specify realy absolute path in the NuGet.Config
<config>
<add key="repositorypath" value="p:\NuGetPackages" />
</config>
<packageRestore>
<add key="enabled" value="True" />
</packageRestore>
After all delete suo files
ps: Will a little trouble with the alteration of exsisting solutions, if they live in sourcecontrol
easiest way is to correcting the path to p:\NuGetPackages in each .csproj
Otherwise it is necessary to reinstall all the refs and manually undo all packages.config marked as deleted in the sourcecontrol

Related

Nuget package missing .target file in build folder

I have build a nuget package at published it to a nuget.server site. But when I try to use the package form the server the .targets file from build folder is not in the file. But if I use the package from a local folder it works as it should. How do I get it to work ?
If i look in the package in the folder on the server it looks ok.
It's not clear to me if you mean using (referencing and restoring) a package, or building (packing) a package.
If the problem is with packing the nupkg, NuGet requires the props and targets files to have specific filenames in specific folders, but if you got it to work at least once, you probably already know that. If this is not the problem with packing, you need to give us more information because not using the correct filename convention is the most common problem and I can't guess what else the problem could be. In particular, if the package is being packed differently on your local machine compared to when it is packed on the server, it means there is something different between how you pack on the two computers, so we need more information about how the build and pack work with your project.
If the problem is with using (restoring) the package, there are a few possibilities. My best guess is that you once had a package without the targets file working correctly, and you restored the package on the server. By design, NuGet packages are immutable which means it's invalid for the contents of a package (same ID and version) to change. This allows NuGet to download the package from a remote feed once, save it in the global package folder (not a cache; they never expire) and the next time NuGet needs to restore the same package (id + version) it uses the one in the global package folder, it does not download again. This means if you once built a bad nupkg and restored it on a machine, then fix the nupkg and kept the same version number, that machine will never get the fixed nupkg. You need to delete it from the global packages folder. I'm not 100% sure, but I think if you have a local file feed and you restore a project that uses packages.config, the nupkg does not get saved in the global packages folder, so doesn't have the same problem. In short, I think the problem is that you changed the nupkg contents once without changing the version number, and one of the machines has the old copy in its global packages folder that it keeps using.
If that's not the problem, the next most likely cause is that the nupkg on the server feed has different contents to the nupkg in the local feed. I've never used NuGet.Server, but some nuget respositories (like nuget.org) do not allow overwriting nupkgs. So, if you pushed a nupkg to your server, fixed a problem in your nupkg without changing the version, then tried to push again, the second push might have failed.
In summary, your question doesn't provide enough information for us to help you, but I wrote about the most common issues above. If it doesn't help, you need to provide us with more information. An example of the problem is the best way to give us enough information to help you.

Nuget xdt transform does not work for config files

I have .NetStandard library. I'm going to use it in .NetFramework and .NetCoreApp applications.
It uses System.Configuration.ConfigurationManager package for work with config files. I need to transform these config files during my library installation.
I found 2 ways:
tools folder in nuget package with install.ps1 file in it
content folder with app.config.install.xdt file in it
Non of them is does not work - nuget doesn't run install.ps1, nuget doesn't transform App.config.
There is a code from csproj:
<ItemGroup>
<Content Include="Content\app.config.install.xdt">
<PackagePath>content</PackagePath>
</Content>
</ItemGroup>
Nuget package contains this file... So I have no idea why it doesn't work.
Is this problem related to .NetStandard? What I'm doing wrong?
Executing ps1 scripts, and XDT transforms are both features that only work with packages.config, but not PackageReference. .NET Core (and I think .NET Standard) projects only work with SDK-style projects, and SDK style projects only support PackageReference. Packages.config only works with "old-style" projects, which may also PackageReference.
The way that Microsoft's ASP.NET Core libraries deal with this difference is that they no longer read settings directly from web.config. Instead the program has to register callback functions that will modify an existing in-memory options object. For example
services.AddMyService(options =>
{
options.setting = newValue;
});
This has some advantages to your users.
They are no longer limited to storing the configuration value in the location the library author demanded. They can choose to load configuration from a database, a configuration service, an xml file, a json file, or just hard-code it in the app. But it lets each developer choose what's best for their own system.
If the user overrides a setting that the package puts in the config file, and each update of the package overrides the user's preference, the user gets annoyed that the package doesn't respect their choice to change the default.
If the user doesn't want to override a setting that the package put in the config file, and the package author doesn't want to overwrite the config file each update, then it's very difficult for the package author to change a default value.
ASP.NET Core's new model is better for everyone because the package author creates the options object and pre-populates it with default values and then call the user's delegate method allowing them to change the settings they care about. If the package author wants to change a default value, they do so in their own code, publish a new package, and users that don't change the value get the new default, and users who explicitly set the value in their code keep using the value they want to, from whatever configuration store they want.
So, the TL:DR answer is that you can't do what you asked for with PackageReference projects, but I hope my longer answer has given you ideas how you can redesign your library which gives better both the package author and package user a better experience.

.NET Core 2 application reference NuGet package with static files

I have a .NET Core 2 application and I'm trying to reference a NuGet package which contains static files and have them copied to my application similarly to how the "content" directory worked in the past.
According to the following https://blog.nuget.org/20160126/nuget-contentFiles-demystified.html this looks to be supported under a "contentFiles" directory.
I've found the following package which looks to support the new schema:
https://www.nuget.org/packages/ContentFilesExample/
And added a reference to it by adding the following to my .csproj file:
<PackageReference Include="ContentFilesExample" Version="1.0.2" />
Now when I run dotnet restore it doesn't copy anything to my application. I've been searching through the GitHub issues but it's hard to follow what is outdated and what is supported.
I'd appreciate it if someone could let me know if this is supported and what I could possibly be doing wrong. If it's not supported please could you point me in the direction of the correct GitHub issue to follow. Thanks
With PackageReference, the files are never copied over to the project. Rather the content files live in the global packages folder as immutable entities. You can still refer to these files as if these were expanded in your project.
If you use Visual Studio 2017, you can see these as refs as shown below. You can refer to .csproj.nuget.g.props file in the obj directory to find out the details of the files refs/links.
Have you looked at NuGet pkg Microsoft.AspNetCore.StaticFiles (2.0.0) ?

NuGet reference in wrong directory structure

My Web2 solution is failing to compile because some of the packages were hosted in a different directory structure to the rest of the solution, and I deleted this structure and the corresponding "packages" folder.
I used Update-Package -reinstall
Hoping that this would fix it... however it still kicks out this error message on build:
This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is ..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props
Now as far as I can tell all the references should be OK, packages.config says:
<package id="Microsoft.Net.Compilers" version="1.0.0" targetFramework="net45" developmentDependency="true" />
And the directory structure exists
--Solution Dir
|-- packages
|--Microsoft.Net.Compilers.1.0.0
I tried updating the package and got version 1.3.2, but the error message remained the same, ie version 1.0.0 was missing.
Theres' clearly some reference to this floating around somewhere - but I don't know where to start looking. I'm assuming the ..\packages in the path indicates its looking for the package in the external directory location (as one up was where the original packages were)
Any ideas?
UPDATE:
I copied the packages folder back to its original location outside the solution directory and .... the issue isn't resolved. So maybe that was never the issue in the first place.
However the error message is still reporting a missing NuGet package that to all appearances is actually there.
This StackOverflow answer got me started on the right track, once I Googled the error message without the ..\ in front of the package location
https://stackoverflow.com/a/32296184/1286358
Then I had to go through and add serveral missing references - presumably because in my hacking attempts to fix the issue I had removed them then not re-referenced them.

EntityDeploySplit error - Microsoft.Data.Entity.Build.Tasks.dll missing

After a clean Windows reformat and installing Visual Studio 2013, trying to build a project with database-first Entity Framework edmx files yields the following error:
The "EntityDeploySplit" task could not be loaded from the assembly
C:\Program Files
(x86)\MSBuild\12.0\bin\Microsoft.Data.Entity.Build.Tasks.dll. Could
not load file or assembly 'file:///C:\Program Files
(x86)\MSBuild\12.0\bin\Microsoft.Data.Entity.Build.Tasks.dll' or one
of its dependencies. The system cannot find the file specified.
Confirm that the declaration is correct, that the assembly
and all its dependencies are available, and that the task contains a
public class that implements Microsoft.Build.Framework.ITask.
Is there some way to install this separately? What is this assembly included with by default?
UPDATE: This also manifests itself when looking for the EntityClean task. I'm inclined to think that it checks the bin first, since another developer who was running it fine tried a clean / rebuild and then this started showing up.
I found the accepted answer to be a little confusing, below are the steps that worked for me.
Open C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Data.Entity.targets in notepad.
Alter the UsingTask elements to:
<UsingTask TaskName="EntityDeploySplit"
AssemblyFile="Microsoft.Data.Entity.Build.Tasks.dll" />
<UsingTask TaskName="EntityDeploy"
AssemblyFile="Microsoft.Data.Entity.Build.Tasks.dll" />
<UsingTask TaskName="EntityDeploySetLogicalNames"
AssemblyFile="Microsoft.Data.Entity.Build.Tasks.dll" />
<UsingTask TaskName="EntityClean"
AssemblyFile="Microsoft.Data.Entity.Build.Tasks.dll" />
I ran into this problem and was able to fix it as I have described below. Your paths and variables may be different.
I found that when my project builds it points to this target file:
C:\Program Files (x86)\MSBuild\12.0\Bin\Microsoft.Data.Entity.targets
That target file appears to just be a placeholder. There is an Import element, in that file, that points to $(MSBuildFrameworkToolsPath)\Microsoft.Data.Entity.targets which runs the target file located at that path. I searched registry and found that MSBuildFrameworkToolsPath is a registry entry with the value of C:\Windows\Microsoft.NET\Framework\v4.0.30319\
I went to the targets file that was referenced and search for the UsingTask element that was specified in my exception. Inside the UsingTask element, the AssemblyFile attribute was pointed to $(MSBuildBinPath)\Microsoft.Data.Entity.Build.Tasks.dll. I searched the registry and found that the MSBuildBinPath registry entry was pointed to c:\Windows\Microsoft.NET\Framework\v3.5\
I'm not sure why it was pointed to that, maybe a Framework or Visual Studio installation didn't clean it up. Finally, I changed all my UsingTask elements' AssemblyFile attributes to:
$(MSBuildFrameworkToolsPath)\Microsoft.Data.Entity.Build.Tasks.dll
I used the same variable that was in the MSBuild Bin target file.
Hope this helps.
I give a lot of credit to Andy Mahaffey for his answer, without it I would not have found what I did.
I followed along his line of research but didn't like the idea of just changing the UsingTasks' attributes. I opened up the "C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Data.Entity.targets" file and I found the first thing it says after the opening Project element is this comment:
<!-- This .targets file can be used by updating Microsoft.Common.targets to
include the line below (as the last import element just before the end project tag)
<Import Project="$(MSBuildBinPath)\Microsoft.Data.Entity.targets" Condition="Exists('$(MSBuildBinPath)\Microsoft.Data.Entity.targets')"/>
-->
I followed it's suggestion and presto, problems solved.
I hope this helps!
TLDR
Paste the line below as the last element before the tag in the following file. C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets
<Import Project="$(MSBuildBinPath)\Microsoft.Data.Entity.targets" Condition="Exists('$(MSBuildBinPath)\Microsoft.Data.Entity.targets')"/>
In my case, I had accidentally created two copies of one of my .edmx files, one in a subfolder, where I didn't notice it. Once I deleted the extra one, everything was fine.