PackageReference dans les fichiers projet

Les références de package utilisent des éléments MSBuild <PackageReference> pour spécifier des dépendances de package NuGet directement dans les fichiers projet, et non un fichier packages.config séparé. L’utilisation de PackageReference n’a pas d’impact sur les autres aspects de NuGet. Par exemple, les paramètres des fichiers NuGet.Config (notamment les sources de packages) continuent d’être appliqués, comme cela est expliqué dans Configurations courantes de NuGet.

Avec PackageReference, vous pouvez aussi utiliser des conditions MSBuild pour choisir des références de package par version cible de .NET Framework ou autre type de regroupement. Elle permet également de mieux contrôler les dépendances et les flux de contenu. Pour plus d’informations, consultez Commandes pack et restore NuGet comme cibles MSBuild.

Prise en charge de type de projet

Par défaut, PackageReference est utilisé pour les projets .NET Core, les projets .NET Standard et les projets UWP ciblant Windows 10 Build 15063 (Creators Update) et version ultérieure, excepté les projets C++ UWP. Les projets .NET Framework prennent en charge PackageReference, mais utilisent par défaut packages.config. Pour utiliser PackageReference, migrez les dépendances de packages.config dans votre fichier projet, puis supprimez packages.config.

Les applications ASP.NET ciblant le .NET Framework incluent uniquement une prise en charge limitée pour PackageReference. Les types de projets C++ et JavaScript ne sont pas pris en charge.

Ajout d’un PackageReference

Ajoutez une dépendance dans votre fichier projet en utilisant la syntaxe suivante :

<ItemGroup>
    <!-- ... -->
    <PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.0" />
    <!-- ... -->
</ItemGroup>

Contrôle des versions des dépendances

Pour spécifier la version d’un package, la convention est la même que pour packages.config :

<ItemGroup>
    <!-- ... -->
    <PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.0" />
    <!-- ... -->
</ItemGroup>

Dans l’exemple ci-dessus, 3.6.0 correspond à n’importe quelle version >= 3.6.0, avec une préférence pour la version la plus ancienne, comme décrit dans Gestion des versions de package.

Utilisation de PackageReference pour un projet sans dépendances de package

Avancé : Si vous n’avez aucun package installé dans un projet (aucune PackageReferences dans le fichier projet et aucun fichier packages.config), mais que vous souhaitez restaurer le projet en tant que style PackageReference, vous pouvez définir une propriété de projet RestoreProjectStyle avec la valeur PackageReference dans votre fichier projet.

<PropertyGroup>
    <!--- ... -->
    <RestoreProjectStyle>PackageReference</RestoreProjectStyle>
    <!--- ... -->
</PropertyGroup>    

Cela peut être utile si vous référencez des projets qui sont de style PackageReference (projets csproj ou de style SDK existants). Cela permet aux packages auxquels ces projets font référence d’être référencés « transitivement » par votre projet.

PackageReference et sources

Dans les projets PackageReference, les versions de dépendance transitive sont résolues au moment de la restauration. Par conséquent, dans les projets PackageReference, toutes les sources doivent être disponibles pour toutes les restaurations.

Versions flottantes

Les versions flottantes peuvent être utilisées avec PackageReference :

<ItemGroup>
    <!-- ... -->
    <PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.*" />
    <PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.0-beta.*" />
    <!-- ... -->
</ItemGroup>

Contrôle des ressources de dépendance

Vous pouvez utiliser une dépendance uniquement comme un atelier de développement et ne pas l’exposer aux projets qui utilisent votre package. Dans ce scénario, vous pouvez utiliser les métadonnées PrivateAssets pour contrôler ce comportement.

<ItemGroup>
    <!-- ... -->

    <PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.0">
        <PrivateAssets>all</PrivateAssets>
    </PackageReference>

    <!-- ... -->
</ItemGroup>

Les balises de métadonnées suivantes permettent de contrôler les ressources de dépendance :

Balise Description Valeur par défaut
IncludeAssets Ces ressources sont consommées. all
ExcludeAssets Ces ressources ne sont pas consommées. Aucune
PrivateAssets Ces ressources sont consommées, mais ne sont pas acheminées vers le projet parent. contentfiles;analyzers;build

Les valeurs autorisées pour ces balises sont les suivantes (les valeurs multiples doivent être séparées par un point-virgule, à l’exception de all et de none qui doivent s’afficher seules) :

Valeur Description
compile Contenu du dossier lib et contrôles permettant de déterminer si votre projet peut être compilé avec les assemblys dans le dossier
runtime Contenu des dossiers lib et runtimes contrôles permettant de déterminer si ces assemblys seront copiés vers le répertoire de sortie de build
contentFiles Contenu du dossier contentfiles
build .props et .targets dans le dossier build
buildMultitargeting (4.0).props et .targets dans le dossier buildMultitargeting, pour le ciblage multi-infrastructures
buildTransitive (5.0 +).props et .targets dans le dossier buildTransitive, pour les ressources qui circulent de manière transitive vers n’importe quel projet consommateur. Consultez la page Fonctionnalité.
analyzers Analyseurs .NET
native Contenu du dossier native
Aucune Aucune des valeurs ci-dessus n’est utilisée.
all Toutes les valeurs ci-dessus sont utilisées (sauf none)
<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>

Étant donné que build n’est pas inclus dans PrivateAssets, les cibles et les propriétés sont acheminées vers le projet parent. Imaginons, par exemple, que la référence ci-dessus soit utilisée dans un projet qui crée un package NuGet appelé AppLogger. AppLogger peut consommer les cibles et les propriétés de Contoso.Utility.UsefulStuff, tout comme les projets peuvent consommer AppLogger.

Remarque

Si la propriété developmentDependency est définie sur true dans un fichier .nuspec, elle marque un package comme dépendance de développement uniquement, ce qui l’empêche d’être inclus en tant que dépendance dans d’autres packages. Avec PackageReference (NuGet 4.8+), cet indicateur signifie également que la propriété exclura les ressources de la compilation. Pour plus d'informations, voir Prise en charge de DevelopmentDependency pour PackageReference.

Ajout d’une condition PackageReference

Vous pouvez utiliser une condition pour contrôler si un package doit être inclus, ainsi que l’endroit où les conditions peuvent utiliser une variable MSBuild ou une variable définie dans le fichier de propriétés ou de cibles. Toutefois, à l’heure actuelle, seule la variable TargetFramework est prise en charge.

Par exemple, supposons que vous souhaitiez cibler netstandard1.4 et net452, mais que l’une de vos dépendances ne s’applique qu’à net452. Dans ce cas, il n’est pas souhaitable qu’un projet netstandard1.4 utilise votre package pour ajouter cette dépendance inutile. Pour éviter cela, spécifiez une condition sur PackageReference de la façon suivante :

<ItemGroup>
    <!-- ... -->
    <PackageReference Include="Newtonsoft.Json" Version="9.0.1" Condition="'$(TargetFramework)' == 'net452'" />
    <!-- ... -->
</ItemGroup>

Dans un package créé à l’aide de ce projet, le fichier Newtonsoft.Json est inclus en tant que dépendance uniquement pour une cible net452 :

The result of applying a Condition on PackageReference with VS2017

Les conditions peuvent également être appliquées au niveau d’un ItemGroup, à tous les éléments enfants PackageReference :

<ItemGroup Condition = "'$(TargetFramework)' == 'net452'">
    <!-- ... -->
    <PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
    <PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.0" />
    <!-- ... -->
</ItemGroup>

GeneratePathProperty

Cette fonctionnalité est disponible avec NuGet 5.0 ou ultérieur, et avec Visual Studio 2019 16.0 ou ultérieur.

Il est parfois souhaitable de référencer des fichiers dans un package à partir d’une cible MSBuild. Dans les projets basés sur packages.config, les packages sont installés dans un dossier relatif au fichier projet. Toutefois, dans PackageReference, les packages sont consommés à partir du dossier global-packages, qui peut varier d’un ordinateur à l’autre.

Pour combler cet écart, NuGet a introduit une propriété qui pointe vers l’emplacement à partir duquel le package sera consommé.

Exemple :

  <ItemGroup>
      <PackageReference Include="Some.Package" Version="1.0.0" GeneratePathProperty="true" />
  </ItemGroup>

  <Target Name="TakeAction" AfterTargets="Build">
    <Exec Command="$(PkgSome_Package)\something.exe" />
  </Target>

En plus, NuGet génère automatiquement des propriétés pour les packages contenant un dossier d’outils.

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

Les propriétés MSBuild et les identités de package n’ont pas les mêmes restrictions. L’identité du package doit donc être modifiée en nom convivial MSBuild, précédée du mot Pkg. Pour vérifier le nom exact de la propriété générée, examinez le fichier nuget.g.props généré.

Alias PackageReference

Dans certains cas rares, différents packages contiennent des classes dans le même espace de noms. À partir de NuGet 5.7 et Visual Studio 2019 Update 7, équivalent à ProjectReference, PackageReference prend en charge Aliases. Par défaut, aucun alias n’est fourni. Lorsqu’un alias est spécifié, tous les assemblys provenant du package annoté doivent être référencés avec un alias.

Vous pouvez examiner des exemples d’utilisation sur NuGet\Samples

Dans le fichier projet, spécifiez les alias comme suit :

  <ItemGroup>
    <PackageReference Include="NuGet.Versioning" Version="5.8.0" Aliases="ExampleAlias" />
  </ItemGroup>

et dans le code, utilisez-le comme suit :

extern alias ExampleAlias;

namespace PackageReferenceAliasesExample
{
...
        {
            var version = ExampleAlias.NuGet.Versioning.NuGetVersion.Parse("5.0.0");
            Console.WriteLine($"Version : {version}");
        }
...
}

Avertissements et erreurs Nuget

Cette fonctionnalité est disponible avec NuGet 4.3 ou ultérieur, et avec Visual Studio 2017 15.3 ou ultérieur.

Pour de nombreux packs et scénarios de restauration, tous les avertissements et erreurs NuGet sont codés et commencent par NU****. Tous les avertissements et erreurs NuGet sont répertoriés dans la documentation de référence.

NuGet suit les propriétés d’avertissement suivantes :

  • TreatWarningsAsErrors considère tous les avertissements comme des erreurs
  • WarningsAsErrors, considère certains avertissements comme des erreurs
  • NoWarn, masque certains avertissements, à l’échelle du projet ou à l’échelle du package.

Exemples :

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

Suppression des avertissements NuGet

Bien qu’il soit recommandé de résoudre tous les avertissements NuGet pendant vos opérations de pack et de restauration, dans certaines situations, la suppression de ces avertissements est justifiée. Pour supprimer un avertissement à l’échelle du projet, procédez comme suit :

<PropertyGroup>
    <PackageVersion>5.0.0</PackageVersion>
    <NoWarn>$(NoWarn);NU5104</NoWarn>
</PropertyGroup>
<ItemGroup>
    <PackageReference Include="Contoso.Package" Version="1.0.0-beta.1"/>
</ItemGroup>

Parfois, les avertissements s’appliquent uniquement à un certain package dans le graphe. Il est possible de choisir de supprimer cet avertissement de manière plus sélective en ajoutant un NoWarn sur l’élément PackageReference.

<PropertyGroup>
    <PackageVersion>5.0.0</PackageVersion>
</PropertyGroup>
<ItemGroup>
    <PackageReference Include="Contoso.Package" Version="1.0.0-beta.1" NoWarn="NU1603" />
</ItemGroup>

Suppression des avertissements de package NuGet dans Visual Studio

Dans Visual Studio, vous pouvez également supprimer des avertissements via l’IDE.

Verrouillage des dépendances

Cette fonctionnalité est disponible avec NuGet 4.9 ou ultérieur, et avec Visual Studio 2017 15.9 ou ultérieur.

L’entrée de la restauration NuGet est un ensemble d’éléments de PackageReference provenant du fichier projet (dépendances de niveau supérieur ou directes). La sortie est une fermeture complète de toutes les dépendances de package, notamment les dépendances transitives. NuGet s’efforce toujours de produire la même fermeture complète des dépendances de package si la liste PackageReference d’entrée ne change pas. Toutefois, tous les scénarios ne s’y prêtent pas. Par exemple :

  • Quand vous utilisez des versions flottantes comme <PackageReference Include="My.Sample.Lib" Version="4.*"/>. L’intention ici est de flotter vers la dernière version à chaque restauration de package. Mais dans certains scénarios, les utilisateurs peuvent exiger le verrouillage du graphe à une version récente donnée et son flottement vers une version ultérieure, si celle-ci est disponible, à la suite d’un mouvement explicite.

  • Une version plus récente du package correspondant aux exigences de version de PackageReference est publiée. Par exemple,

    • Premier jour : Vous spécifiez <PackageReference Include="My.Sample.Lib" Version="4.0.0"/>, mais les versions disponibles sur les dépôts NuGet sont 4.1.0, 4.2.0 et 4.3.0. Dans ce cas, NuGet résout la version en 4.1.0 (la plus proche de la version minimale).

    • Deuxième jour : La version 4.0.0 est publiée. NuGet trouve désormais la correspondance exacte et commence à résoudre la version en 4.0.0.

  • Une version de package donnée est supprimée du dépôt. Bien que nuget.org n’autorise pas la suppression de packages, d’autres dépôts de packages n’ont pas cette contrainte. NuGet trouve donc la meilleure correspondance quand la version supprimée rend impossible la résolution.

Activation du fichier de verrouillage

Pour rendre persistante la fermeture complète des dépendances de package, vous pouvez choisir d’utiliser la fonctionnalité de fichier de verrouillage en définissant la propriété MSBuild RestorePackagesWithLockFile pour votre projet :

<PropertyGroup>
    <!--- ... -->
    <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
    <!--- ... -->
</PropertyGroup>    

Si cette propriété est définie, la restauration NuGet génère un fichier de verrouillage (packages.lock.json) au niveau du répertoire racine du projet qui liste toutes les dépendances du package.

Remarque

Quand un projet a un fichier packages.lock.json dans son répertoire racine, le fichier de verrouillage est toujours utilisé avec la restauration, même si la propriété RestorePackagesWithLockFile n’est pas définie. Une autre façon de choisir cette fonctionnalité consiste à créer un fichier packages.lock.json vide factice dans le répertoire racine du projet.

Comportement de restore avec fichier de verrouillage

Si un fichier de verrouillage est présent pour le projet, NuGet utilise ce fichier de verrouillage pour exécuter restore. NuGet effectue une vérification rapide pour voir si les dépendances de package ont changé, comme indiqué dans le fichier projet (ou les fichiers des projets dépendants). Si aucun changement n’est détecté, il restaure simplement les packages mentionnés dans le fichier de verrouillage. Les dépendances de package ne sont pas réévaluées.

Si NuGet détecte un changement dans les dépendances définies indiquées dans le ou les fichiers projet, il réévalue le graphe du package et met à jour le fichier de verrouillage pour refléter la nouvelle fermeture de package du projet.

Dans CI/CD et d’autres scénarios où vous ne voulez pas changer les dépendances de package à la volée, vous pouvez définir lockedmode avec la valeur true :

Pour dotnet.exe, exécutez :

> dotnet.exe restore --locked-mode

Pour msbuild.exe, exécutez :

> msbuild.exe -t:restore -p:RestoreLockedMode=true

Vous pouvez également définir cette propriété MSBuild conditionnelle dans votre fichier projet :

<PropertyGroup>
    <!--- ... -->
    <RestoreLockedMode>true</RestoreLockedMode>
    <!--- ... -->
</PropertyGroup> 

Si le mode verrouillé est true, soit la restauration restaure les packages exacts figurant dans la liste du fichier de verrouillage, soit elle échoue si vous avez mis à jour les dépendances de package définies pour le projet une fois le fichier de verrouillage créé.

Intégrer le fichier de verrouillage dans votre dépôt source

Si vous générez un exécutable d’application et que le projet en question se trouve à la début de la chaîne de dépendance, archivez le fichier de verrouillage dans le dépôt de code source pour que NuGet puisse l’utiliser durant la restauration.

Toutefois, si votre projet est un projet de bibliothèque que vous ne prévoyez pas de distribuer ou un projet de code commun dont dépendent d’autres projets, n’archivez pas le fichier de verrouillage dans le cadre de votre code source. Le fait de conserver le fichier de verrouillage ne pose aucun risque. Toutefois, vous ne pouvez pas utiliser les dépendances de package verrouillées pour le projet de code commun, qui figurent dans la liste du fichier de verrouillage, durant la restauration/génération d’un projet qui dépend de ce projet de code commun.

par exemple

ProjectA
  |------> PackageX 2.0.0
  |------> ProjectB
             |------>PackageX 1.0.0

Si ProjectA a une dépendance à un PackageX version 2.0.0 et qu’il référence également ProjectB qui dépend de PackageX version 1.0.0, le fichier de verrouillage pour ProjectB liste une dépendance à PackageX version 1.0.0. Toutefois, quand ProjectA est généré, son fichier de verrouillage contient une dépendance à PackageX version 2.0.0 et non à1.0.0 (qui figure dans la liste du fichier de verrouillage pour ProjectB). Le fichier de verrouillage d’un projet de code commun a donc peu de contrôle sur les packages résolus pour les projets qui en dépendent.

Extensibilité du fichier de verrouillage

Vous pouvez contrôler divers comportements de restauration avec un fichier de verrouillage, comme décrit ci-dessous :

Option NuGet.exe Option dotnet Option MSBuild équivalente Description
-UseLockFile --use-lock-file RestorePackagesWithLockFile Choisit d’utiliser d’un fichier de verrouillage.
-LockedMode --locked-mode RestoreLockedMode Active le mode verrouillé pour la restauration. Ceci est utile dans les scénarios CI/CD dans lesquels vous voulez obtenir des générations renouvelables.
-ForceEvaluate --force-evaluate RestoreForceEvaluate Cette option est utile avec des packages dont la version flottante est définie dans le projet. Par défaut, la restauration NuGet ne met pas automatiquement à jour la version du package à chaque restauration, sauf si vous exécutez la restauration avec cette option .
-LockFilePath --lock-file-path NuGetLockFilePath Définit un emplacement de fichier de verrouillage personnalisé pour un projet. Par défaut, NuGet prend en charge packages.lock.json au niveau du répertoire racine. Si vous avez plusieurs projets dans le même répertoire, NuGet prend en charge le fichier de verrouillage packages.<project_name>.lock.json spécifique au projet.

AssetTargetFallback

La propriété AssetTargetFallback vous permet de spécifier des versions de framework compatibles supplémentaires pour les projets que les références de projet et les packages NuGet consomment.

Si vous spécifiez une dépendance de package à l’aide de PackageReference, mais que ce package ne contient pas de ressources compatibles avec la version cible de .Net Framework de votre projet, la propriété AssetTargetFallback entre en jeu. La compatibilité du package référencé est vérifiée à nouveau à l’aide de chaque framework cible spécifié dans AssetTargetFallback. Lorsqu’un project ou un package est référencé via AssetTargetFallback, l’avertissement NU1701 est déclenché.

Reportez-vous au tableau suivant pour vois comment AssetTargetFallback affecte la compatibilité.

Framework de projet AssetTargetFallback Framework de package 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, échec avec NU1202
.NET Core App 3.1 net472;net471 .NET Framework 4.7.2 .NET Framework 4.7.2 avec NU1701

Plusieurs frameworks peuvent être spécifiés à l’aide de ; en tant que séparateur. Pour ajouter une framework de secours, vous pouvez effectuer les opérations suivantes :

<AssetTargetFallback Condition=" '$(TargetFramework)'=='netcoreapp3.1' ">
    $(AssetTargetFallback);net472;net471
</AssetTargetFallback>

Vous pouvez laisser $(AssetTargetFallback) si vous souhaitez remplacer, au lieu d’ajouter aux valeurs existantes AssetTargetFallback.

Remarque

Si vous utilisez un projet basé sur le Kit de développement logiciel (SDK) .NET, les valeurs appropriées $(AssetTargetFallback) sont configurées et vous n’avez pas besoin de les définir manuellement.

$(PackageTargetFallback) était une fonctionnalité antérieure qui devait résoudre ce défi, mais elle est fondamentalement rompue et ne doit pas être utilisée. Pour migrer $(PackageTargetFallback) vers $(AssetTargetFallback), modifiez simplement le nom de propriété.