57
votes

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?

3
I suspect that since dotnet restore worked but nuget did not that nuget on Team City is an older version that does not understand PackageReferences. NuGet would need to be at least version 4.0.Matt Ward
We're having the same issue, where dotnet restore works but nuget restore doesn't. And for us, it's happening both on TeamCity and locally.r12
Things are even weirder for me. nuget restore tells me it can't resolve a single package. If I then use dotnet restore it downloads some packages, but then my msbuild still fails to compile the solution due to missing packages. If I then do nuget restore again, it can suddendly find everything, and a subsequent msbuild then works... Clearly something very strange is going on with how packages are configured in my project.Jake

3 Answers

77
votes

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 as nuget.exe or Visual Studio-integrated tooling sees the packages.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 a packages.config project only downloads the files.
  • PackageReference: The project contains MSBuild items that reference a NuGet package. Unlike packages.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 the obj 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 the dotnet 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.Objectwill not be available to the compiler.

5
votes

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+)
-1
votes

nuget restore will ensure all of your NuGet dependencies are downloaded and available to your project. Whereas dotnet restore is a complete restoration of all NuGet dependencies as well as references and project specific tools. Meaning that if you run nuget restore, you are only restoring NuGet packages.

According to docs.microsoft.com: Dotnet Restore

The dotnet restore command uses NuGet to restore dependencies as well as project-specific tools that are specified in the project file...