71

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?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Thomas
  • 10,933
  • 14
  • 65
  • 136
  • 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 Aug 27 '17 at 11:21
  • 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 Oct 13 '17 at 17:35
  • 1
    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 Jun 08 '21 at 18:13

4 Answers4

102

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Martin Ullrich
  • 94,744
  • 25
  • 252
  • 217
  • This clarifies things a lot! thank you! In that light, is there any reason to use the package.config mechanism anymore? – Thomas Aug 27 '17 at 11:52
  • 3
    The `content` feature (copying files to the consuming project's source) has been removed and replaced with a `contentFiles` feature. Also, `PackageReference` only works in VS 2017+ (NuGet 4.*, MSBuild 15+) – Martin Ullrich Aug 27 '17 at 12:51
6

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+)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
hsop
  • 3,546
  • 3
  • 20
  • 19
3

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 learn.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...

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Exonto
  • 51
  • 6
0

None of them worked for me. At the time of creating a project I have selected the option to enable Razor runtime optimization. This caused the build error. Enabling Razor Runtime optimization

When I have recreated the same project without that option, it worked fine for me.

dotcoder
  • 2,828
  • 10
  • 34
  • 50