This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Note
Access to this page requires authorization. You can trysigning in orchanging directories.
Access to this page requires authorization. You can trychanging directories.
PackageReference
in project filesPackage references, using<PackageReference>
MSBuild items, specify NuGet package dependencies directly within project files, as opposed to having a separatepackages.config
file. Use of PackageReference doesn't affect other aspects of NuGet; for example, settings inNuGet.Config
files (including package sources) are still applied as explained inCommon NuGet configurations.
With PackageReference, you can also use MSBuild conditions to choose package references per target framework, or other groupings. It also allows for fine-grained control over dependencies and content flow. (See For more detailsNuGet pack and restore as MSBuild targets.)
By default, PackageReference is used for .NET Core projects, .NET Standard projects, and UWP projects targeting Windows 10 Build 15063 (Creators Update) and later, with the exception of C++ UWP projects. .NET Framework projects support PackageReference, but currently default topackages.config
. To use PackageReference,migrate the dependencies frompackages.config
into your project file, then remove packages.config.
ASP.NET apps targeting the full .NET Framework include onlylimited support for PackageReference. C++ and JavaScript project types are unsupported.
Add a dependency in your project file using the following syntax:
<ItemGroup> <!-- ... --> <PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.0" /> <!-- ... --></ItemGroup>
The convention for specifying the version of a package is the same as when usingpackages.config
:
<ItemGroup> <!-- ... --> <PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.0" /> <!-- ... --></ItemGroup>
In the example above, 3.6.0 means any version that is >=3.6.0 with preference for the lowest version, as described onPackage versioning.
Advanced: If you have no packages installed in a project (no PackageReferences in project file and no packages.config file), but want the project to be restored as PackageReference style, you can set a Project property RestoreProjectStyle to PackageReference in your project file.
<PropertyGroup> <!--- ... --> <RestoreProjectStyle>PackageReference</RestoreProjectStyle> <!--- ... --></PropertyGroup>
This may be useful, if you reference projects which are PackageReference styled (existing csproj or SDK-style projects). This will enable packages that those projects refer to, to be "transitively" referenced by your project.
In PackageReference projects, the transitive dependency versions are resolved at restore time. As such, in PackageReference projects all sources need to be available for all restores.
Floating versions are supported withPackageReference
:
<ItemGroup> <!-- ... --> <PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.*" /> <PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.0-beta.*" /> <!-- ... --></ItemGroup>
You might be using a dependency purely as a development harness and might not want to expose that to projects that will consume your package. In this scenario, you can use thePrivateAssets
metadata to control this behavior.
<ItemGroup> <!-- ... --> <PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.0"> <PrivateAssets>all</PrivateAssets> </PackageReference> <!-- ... --></ItemGroup>
The following metadata tags control dependency assets:
Tag | Description | Default Value |
---|---|---|
IncludeAssets | These assets will be consumed | all |
ExcludeAssets | These assets will not be consumed | none |
PrivateAssets | These assets will be consumed but won't flow to the parent project | contentfiles;analyzers;build |
Allowable values for these tags are as follows, with multiple values separated by a semicolon except withall
andnone
which must appear by themselves:
Value | Description |
---|---|
compile | Contents of thelib folder and controls whether your project can compile against the assemblies within the folder |
runtime | Contents of thelib andruntimes folder and controls whether these assemblies will be copied out to the build output directory |
contentFiles | Contents of thecontentfiles folder |
build | .props and.targets in thebuild folder |
buildMultitargeting | (4.0).props and.targets in thebuildMultitargeting folder, for cross-framework targeting |
buildTransitive | (5.0+).props and.targets in thebuildTransitive folder, for assets that flow transitively to any consuming project. See thefeature page. |
analyzers | .NET analyzers |
native | Contents of thenative folder |
none | None of the above are used. |
all | All of the above (exceptnone ) |
<ItemGroup> <!-- ... --> <!-- Everything except the content files will be consumed by the project --> <!-- Everything except content files and analyzers will flow to the parent project--> <PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.0"> <IncludeAssets>all</IncludeAssets> <!-- Default is `all`, can be omitted--> <ExcludeAssets>contentFiles</ExcludeAssets> <PrivateAssets>contentFiles;analyzers</PrivateAssets> </PackageReference> <!-- ... --> <!-- Everything except the compile will be consumed by the project --> <!-- Everything except contentFiles will flow to the parent project--> <PackageReference Include="Contoso.Utility.SomeOtherUsefulStuff" Version="3.6.0"> <ExcludeAssets>compile</ExcludeAssets> <PrivateAssets>contentFiles</PrivateAssets> </PackageReference> <!-- ... --></ItemGroup>
Note that becausebuild
is not included withPrivateAssets
, targets and propswill flow to the parent project. Consider, for example, that the reference above is used in a project that builds a NuGet package called AppLogger. AppLogger can consume the targets and props fromContoso.Utility.UsefulStuff
, as can projects that consume AppLogger.
Note
WhendevelopmentDependency
is set totrue
in a.nuspec
file, this marks a package as a development-only dependency, which prevents the package from being included as a dependency in other packages. With PackageReference(NuGet 4.8+), this flag also means that it will exclude compile-time assets from compilation. For more information, seeDevelopmentDependency support for PackageReference.
You can use a condition to control whether a package is included, where conditions can use any MSBuild variable or a variable defined in the targets or props file. However, at presently, only theTargetFramework
variable is supported.
For example, say you're targetingnetstandard1.4
as well asnet452
but have a dependency that is applicable only fornet452
. In this case you don't want anetstandard1.4
project that's consuming your package to add that unnecessary dependency. To prevent this, you specify a condition on thePackageReference
as follows:
<ItemGroup> <!-- ... --> <PackageReference Include="Newtonsoft.Json" Version="9.0.1" Condition="'$(TargetFramework)' == 'net452'" /> <!-- ... --></ItemGroup>
A package built using this project will show that Newtonsoft.Json is included as a dependency only for anet452
target:
Conditions can also be applied at theItemGroup
level and will apply to all childrenPackageReference
elements:
<ItemGroup Condition = "'$(TargetFramework)' == 'net452'"> <!-- ... --> <PackageReference Include="Newtonsoft.Json" Version="9.0.1" /> <PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.0" /> <!-- ... --></ItemGroup>
This feature is available with NuGet5.0 or above and with Visual Studio 201916.0 or above.
Sometimes it is desirable to reference files in a package from an MSBuild target.Inpackages.config
based projects, the packages are installed in a folder relative to the project file. However in PackageReference, the packages areconsumed from theglobal-packages folder, which can vary from machine to machine.
To bridge that gap, NuGet introduced a property that points to the location from which the package will be consumed.
Example:
<ItemGroup> <PackageReference Include="Some.Package" Version="1.0.0" GeneratePathProperty="true" /> </ItemGroup> <Target Name="TakeAction" AfterTargets="Build"> <Exec Command="$(PkgSome_Package)\something.exe" /> </Target>
Additionally NuGet will automatically generate properties for packages containing a tools folder.
<ItemGroup> <PackageReference Include="Package.With.Tools" Version="1.0.0" /> </ItemGroup> <Target Name="TakeAction" AfterTargets="Build"> <Exec Command="$(PkgPackage_With_Tools)\tools\tool.exe" /> </Target>
MSBuild properties and package identities do not have the same restrictions so the package identity needs to be changed to an MSBuild friendly name, prefixed by the wordPkg
.To verify the exact name of the property generated, look at the generatednuget.g.props file.
In some rare instances different packages will contain classes in the same namespace. Starting with NuGet 5.7 & Visual Studio 2019 Update 7, equivalent to ProjectReference, PackageReference supportsAliases
.By default no aliases are provided. When an alias is specified,all assemblies coming from the annotated package with need to be referenced with an alias.
You can look at sample usage atNuGet\Samples
In the project file, specify the aliases as follows:
<ItemGroup> <PackageReference Include="NuGet.Versioning" Version="5.8.0" Aliases="ExampleAlias" /> </ItemGroup>
and in the code use it as follows:
extern alias ExampleAlias;namespace PackageReferenceAliasesExample{... { var version = ExampleAlias.NuGet.Versioning.NuGetVersion.Parse("5.0.0"); Console.WriteLine($"Version : {version}"); }...}
This feature is available with NuGet4.3 or above and with Visual Studio 201715.3 or above.
For many pack and restore scenarios, all NuGet warnings and errors are coded, and start withNU****
. All NuGet warnings and errors are listed in thereference documentation.
NuGet observes the following warning properties:
TreatWarningsAsErrors
, treat all warnings as errorsWarningsAsErrors
, treat specific warnings as errorsNoWarn
, hide specific warnings, either project-wide or package-wide.Examples:
<PropertyGroup> <TreatWarningsAsErrors>true</TreatWarningsAsErrors></PropertyGroup>...<PropertyGroup> <WarningsAsErrors>$(WarningsAsErrors);NU1603;NU1605</WarningsAsErrors></PropertyGroup>...<PropertyGroup> <NoWarn>$(NoWarn);NU5124</NoWarn></PropertyGroup>...<ItemGroup> <PackageReference Include="Contoso.Package" Version="1.0.0" NoWarn="NU1605" /></ItemGroup>
While it is recommended that you resolve all NuGet warnings during your pack and restore operations, in certain situations suppressing them is warranted.To suppress a warning project wide, consider doing:
<PropertyGroup> <PackageVersion>5.0.0</PackageVersion> <NoWarn>$(NoWarn);NU5104</NoWarn></PropertyGroup><ItemGroup> <PackageReference Include="Contoso.Package" Version="1.0.0-beta.1"/></ItemGroup>
Sometimes warnings apply only to a certain package in the graph. We can choose to suppress that warning more selectively by adding aNoWarn
on the PackageReference item.
<PropertyGroup> <PackageVersion>5.0.0</PackageVersion></PropertyGroup><ItemGroup> <PackageReference Include="Contoso.Package" Version="1.0.0-beta.1" NoWarn="NU1603" /></ItemGroup>
When in Visual Studio, you can alsosuppress warnings through the IDE.
This feature is available with NuGet4.9 or above and with Visual Studio 201715.9 or above.
Input to NuGet restore is a set ofPackageReference
items from the project file (top-level or direct dependencies) and the output is a full closure of all the package dependencies including transitive dependencies. NuGet tries to always produce the same full closure of package dependencies if the input PackageReference list has not changed. However, there are some scenarios where it is unable to do so. For example:
When you use floating versions like<PackageReference Include="My.Sample.Lib" Version="4.*"/>
. While the intention here is to float to the latest version on every restore of packages, there are scenarios where users require the graph to be locked to a certain latest version and float to a later version, if available, upon an explicit gesture.
A newer version of the package matching PackageReference version requirements is published. E.g.
Day 1: if you specified<PackageReference Include="My.Sample.Lib" Version="4.0.0"/>
but the versions available on theNuGet repositories were 4.1.0, 4.2.0 and 4.3.0. In this case, NuGet would have resolved to 4.1.0 (nearest minimum version)
Day 2: Version 4.0.0 gets published. NuGet will now find the exact match and start resolving to 4.0.0
A given package version is removed from the repository. Though nuget.org does not allow package deletions, not all package repositories have this constraint. This results in NuGet finding the best match when it cannot resolve to the deleted version.
In order to persist the full closure of package dependencies you can opt-in to the lock file feature by setting the MSBuild propertyRestorePackagesWithLockFile
for your project:
<PropertyGroup> <!--- ... --> <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile> <!--- ... --></PropertyGroup>
If this property is set, NuGet restore will generate a lock file -packages.lock.json
file at the project root directory that lists all the package dependencies.
Note
Once a project haspackages.lock.json
file in its root directory, the lock file is always used with restore even if the propertyRestorePackagesWithLockFile
is not set. So another way to opt-in to this feature is to create a dummy blankpackages.lock.json
file in the project's root directory.
restore
behavior with lock fileIf a lock file is present for project, NuGet uses this lock file to runrestore
. NuGet does a quick check to see if there were any changes in the package dependencies as mentioned in the project file (or dependent projects' files) and if there were no changes it just restores the packages mentioned in the lock file. There is no re-evaluation of package dependencies.
If NuGet detects a change in the defined dependencies as mentioned in the project file(s), it re-evaluates the package graph and updates the lock file to reflect the new package closure for the project.
For CI/CD and other scenarios, where you would not want to change the package dependencies on the fly, you can do so by setting thelockedmode
totrue
:
For dotnet.exe, run:
> dotnet.exe restore --locked-mode
For msbuild.exe, run:
> msbuild.exe -t:restore -p:RestoreLockedMode=true
You may also set this conditional MSBuild property in your project file:
<PropertyGroup> <!--- ... --> <RestoreLockedMode>true</RestoreLockedMode> <!--- ... --></PropertyGroup>
If locked mode istrue
, restore will either restore the exact packages as listed in the lock file or fail if you updated the defined package dependencies for the project after lock file was created.
If you are building an application, an executable and the project in question is at the start of the dependency chain then do check in the lock file to the source code repository so that NuGet can make use of it during restore.
However, if your project is a library project that you do not ship or a common code project on which other projects depend upon, youshould not check in the lock file as part of your source code. There is no harm in keeping the lock file but the locked package dependencies for the common code project may not be used, as listed in the lock file, during the restore/build of a project that depends on this common-code project.
Eg.
ProjectA |------> PackageX 2.0.0 |------> ProjectB |------>PackageX 1.0.0
IfProjectA
has a dependency on aPackageX
version2.0.0
and also referencesProjectB
that depends onPackageX
version1.0.0
, then the lock file forProjectB
will list a dependency onPackageX
version1.0.0
. However, whenProjectA
is built, its lock file will contain a dependency onPackageX
version2.0.0
andnot1.0.0
as listed in the lock file forProjectB
. Thus, the lock file of a common code project has little say over the packages resolved for projects that depend on it.
You can control various behaviors of restore with lock file as described below:
NuGet.exe option | dotnet option | MSBuild equivalent option | Description |
---|---|---|---|
-UseLockFile | --use-lock-file | RestorePackagesWithLockFile | Opts into the usage of a lock file. |
-LockedMode | --locked-mode | RestoreLockedMode | Enables locked mode for restore. This is useful in CI/CD scenarios where you want repeatable builds. |
-ForceEvaluate | --force-evaluate | RestoreForceEvaluate | This option is useful with packages with floating version defined in the project. By default, NuGet restore will not update the package version automatically upon each restore unless you run restore with this option. |
-LockFilePath | --lock-file-path | NuGetLockFilePath | Defines a custom lock file location for a project. By default, NuGet supportspackages.lock.json at the root directory. If you have multiple projects in the same directory, NuGet supports project specific lock filepackages.<project_name>.lock.json |
The NuGet dependency resolver follows the4 rules as described in the dependency resolution document.
In order to improve the performance and scalability of the restore operation, the restore algorithm was rewritten in the 6.12 release.As of the 6.12 release, the new restore algorithm is enabled by default for all PackageReference projects.While the new restore algorithm is is functionally equivalent to the previous one, as with any software, bugs are possible.To revert to the previous implementation, set the MSBuild propertyRestoreUseLegacyDependencyResolver
totrue
.
Should you face restore failures in 6.12, .NET 9 or 17.12, that weren't reproducing in earlier versions, pleasefile an issue on GitHub.Any differences between the old and new algorithms may have different impacts, such as during compilation or at runtime.There's also a chance that changes don't lead to failures, but different package versions being restored.If you think you may be impacted by any changes, here are the steps you can take to verify whether the changes in the NuGet restore algorithm are the root cause.
Restore writes its results in theMSBuildProjectExtensionsPath
directory, which can be compared with the new and old algorithms to find differences.Usually this is theobj
folder of your build.You can usemsbuild.exe
ordotnet.exe
for the next steps.
obj
folder for your project.msbuild -t:restore
obj
to a location indicating that it's thenew
behavior.msbuild -t:restore -p:RestoreUseLegacyDependencyResolver="true"
obj
to a location indicating that it's thelegacy
behavior.If you follow the above method, there should be exactly 1 difference between theproject.assets.json
files:
"projectStyle": "PackageReference",+ "restoreUseLegacyDependencyResolver": true, "fallbackFolders": [
If there are any more differences, pleasefile an issue on GitHub with all the details.
TheAssetTargetFallback
property lets you specify additional compatible framework versions for projects that your project references and NuGet packages that your project consumes.
If you specify a package dependency usingPackageReference
but that package doesn't contain assets that are compatible with your projects's target framework, theAssetTargetFallback
property comes into play. The compatibility of the referenced package is rechecked using each target framework that's specified inAssetTargetFallback
.When aproject
or apackage
is referenced throughAssetTargetFallback
, theNU1701 warning will be raised.
Refer to the table below for examples of howAssetTargetFallback
affects compatibility.
Project framework | AssetTargetFallback | Package frameworks | Result |
---|---|---|---|
.NET Framework 4.7.2 | .NET Standard 2.0 | .NET Standard 2.0 | |
.NET Core App 3.1 | .NET Standard 2.0, .NET Framework 4.7.2 | .NET Standard 2.0 | |
.NET Core App 3.1 | .NET Framework 4.7.2 | Incompatible, fail withNU1202 | |
.NET Core App 3.1 | net472;net471 | .NET Framework 4.7.2 | .NET Framework 4.7.2 withNU1701 |
Multiple frameworks can be specified using;
as a delimiter. To add a fallback framework you can do the following:
<AssetTargetFallback Condition=" '$(TargetFramework)'=='netcoreapp3.1' "> $(AssetTargetFallback);net472;net471</AssetTargetFallback>
You can leave off$(AssetTargetFallback)
if you wish to overwrite, instead of add to the existingAssetTargetFallback
values.
Note
If you are using a.NET SDK based project, appropriate$(AssetTargetFallback)
values are configured and you do not need to set them manually.
$(PackageTargetFallback)
was an earlier feature that attempted to address this challenge, but it is fundamentally broken andshould not be used. To migrate from$(PackageTargetFallback)
to$(AssetTargetFallback)
, simply change the property name.
The .NET Runtime is constantly evolving, with performance improvements and new APIs each release.There is a lot of functionality that's available within the runtime, but also as packages, such asSystem.Text.Json. This can often lead to aSystem.Text.Json 8.0.0
in a project targeting.NET 9
or.NET 8
. This dependency is unnecessary and the build conflict resolution would not use the assembly coming from the package since it's already available in the .NET Runtime.Starting in inNuGet version 6.13 and .NET SDK 9.0.200,PrunePackageReference
enables the pruning of these packages at restore time for .NET SDK based projects.
Package pruning is available as an opt-in feature with the .NET 9 SDK, and will be enabled by default for all.NET
frameworks and>= .NET Standard 2.0
starting with .NET 10 SDK.
Package pruning is only available with the default dependency resolver asreleased in 6.12.
The list of packages to be pruned is defined with thePrunePackageReference
item.
Attributes | Description |
---|---|
Version | Specifies the maximum version to be pruned.1.0.0 means that all packages up to and including 1.0.0 will be pruned. For1.0.0 ,0.9.0 and1.0.0 will be pruned, but1.0.1 would not. |
The following properties can be used to modify the pruning behavior.
PropertyName | Description |
---|---|
RestoreEnablePackagePruning | Enables package pruning for the packages specified withPrunePackageReference . This property is per target framework and the valid values aretrue andfalse . Defaults may differ based on the .NET SDK as defined above. |
The .NET SDK predefines the list of packages to be pruned for you.
When a package is specified to be pruned during restore, it is removed from the dependency graph. This package is not downloaded and does not appear in any of the outputs of NuGet. When a package is pruned, there is a detailed verbosity message indicating that the package has been removed for the given target framework.
Pruning is only supported for transitive packages, meaning packages that are referenced by other packages or projects. The following table illustrates various package pruning behaviors.
Dependency disposition | Behavior |
---|---|
Matches the ID of a transitive package coming through another package | Prune |
Matches the ID of a transitive package coming through another project | Prune |
Matches the ID of a directPackageReference | Raise theNU1510 warning and do not prune |
Matches the ID of aProjectReference | Raise theNU1511 warning and do not prune |
The benefits of package pruning are two-fold:
NuGetAudit
Pruning is particularly valuable whenauditing packages withNuGetAuditMode
is set toall
. If you are using the .NET 9, we recommend you try out pruning by settingRestoreEnablePackagePruning
totrue
.
Was this page helpful?
Was this page helpful?