'dotnet restore' vs. 'nuget restore' with TeamCity
I have an ASP.NET Core project that builds properly with Visual Studio, but it doesn't build under MSBuild.
It doesn't find all the common libraries (system, etc.).
I'm using TeamCity and part of the build process is a nuget restore
.
I tried to do the same steps as TeamCity, but manually with MSBuild, and it failed, not finding the libraries.
I added a dotnet restore
step and then it worked.
So, what is the difference between a nuget restore
and a dotnet restore
?
Solution 1:
Both nuget restore
and dotnet restore
are roughly the same: They perform a NuGet restore operation.
The only difference: dotnet restore
is a convenience wrapper to invoke dotnet msbuild /t:Restore
which invokes an MSBuild-integrated restore. This only works on MSBuild distributions that include NuGet, such as Visual Studio 2017 (full Visual Studio, build tools) or Mono 5.2+ (=> msbuild /t:Restore
) and the .NET Core SDK which provides this convenience command.
At the moment, there are two ways of how NuGet packages can be used in projects (three actually, but let's ignore project.json
on UWP for the moment):
-
packages.config
: The "classic" way of referencing NuGet packages. This assumes NuGet is a separate tool and MSBuild doesn't know anything about NuGet. A NuGet client such asnuget.exe
or Visual Studio-integrated tooling sees thepackages.config
file and downloads the referenced packages into a local folder on restore. A package install modifies the project to reference assets out of this local folder. So a restore for apackages.config
project only downloads the files. -
PackageReference
: The project contains MSBuild items that reference a NuGet package. Unlikepackages.config
, only the direct dependencies are listed and the project file does not directly reference any assets (DLL files, content files) out of packages. On restore, NuGet figures out the dependency graph by evaluating the direct and transitive dependencies, makes sure all packages are downloaded into the user's global package cache (not solution-local so it is only downloaded once) and write an assets file into theobj
folder that contains a list of all packages and assets that the project uses, as well as additional MSBuild targets if any package contains build logic that needs to be added to a project. So a NuGet restore may download packages if they are not already in the global cache and create this assets file. In addition to package references, the project can also reference CLI tools, which are NuGet packages containing additional commands that will be available for thedotnet
in the project directory.
The msbuild-integrated restore only works for PackageReference
type projects (.NET Standard, .NET Core by default, but it is opt-in for any .NET project) and not for packages.config
projects. If you use a new version of nuget.exe
(e.g. 4.3.0), it is able to restore both project types.
Your error about missing types is a bit more interesting: The "reference assemblies" (libraries that are passed as input to the compiler) are not installed on the system but come via NuGet packages. So as long as the NuGet packages are missing from the global package cache or the obj/project.assets.json
file has not been generated by a restore operation, fundamental types like System.Object
will not be available to the compiler.
Solution 2:
I had similar problems with a .NET Core 2 project that would build just fine on my workstation - both within Visual Studio 2017 and using MSBuild only - but did not build in TeamCity. The error message was:
C:\Program Files\dotnet\sdk\2.1.4\Sdks\Microsoft.NET.Sdk\build\Microsoft.PackageDependencyResolution.targets(327, 5):
Assets file 'D:\TeamCity\buildAgent\work\596486b1d4e7a8e7\Source\Integrations\SomeAPI\obj\project.assets.json' not found.
Run a NuGet package restore to generate this file.
In my build configuration I already had a NuGet install step before the build step:
- NuGetversion: 3.4.4
- Restore Mode: Install
It turned out I had to use:
- NuGet version: 4.0.0 or higher
- Restore Mode: Restore (Requires NuGet 2.7+)