NuGet en 5 min

NuGet est un outil facilitant le téléchargement de dépendances externes. Ces dépendances peuvent être téléchargées et ajoutées à un projet Visual Studio ou indépendamment de l’IDE, directement dans un répertoire.
NuGet peut aussi créer et uploader des packages sur un repository.

La documentation de NuGet est plutôt bien faite:

Le but de cet article n’est pas de paraphraser la documentation mais d’être un aide-mémoire sur les principales fonctionnalités de NuGet.

Installation de Nuget

Dans Visual Studio

Pour les versions précédant Visual Studio 2012, il est nécessaire d’installer NuGet après avoir installé Visual Studio: Install Nuget.

A partir de Visual Studio 2012, NuGet est livré avec l’IDE. On peut vérifier la version en cliquant sur le menu Help puis About Microsoft Visual Studio. Il faut ensuite regarder la version de NuGet Package Manager.

On peut toutefois mettre à jour la version livrée en faisant:

  1. Cliquer dans le menu sur Tools puis sur Extensions and Updates
  2. Dans la boite de dialogue, sélectionner l’onglet Tab
  3. Sélectionner Visual Studio Gallery
  4. Sélectionner NuGet Package Manager for Visual Studio
  5. Cliquer sur Update.

Voici les versions du NuGet livrées avec Visual Studio:

Visual Studio 2012 (11.0) NuGet 2.0
Visual Studio 2013 (12.0) NuGet 2.7
Visual Studio 2015 (14.0) NuGet 2.8.6
Visual Studio 2017 (15.0) NuGet 4.0.0
NuGet 4.1.0

La version inclue de NuGet dans Visual Studio n’est accessible qu’à partir du Package Manager ou du Package Manager Console.

Téléchargement direct de nuget.exe

Nuget.exe peut être directement téléchargé sur nuget.org/downloads.

NuGet à la ligne de commandes

Il est possible d’utiliser NuGet à la ligne de commandes sans Visual Studio. On peut le télécharger directement sur: NuGet CLI

Le fichier téléchargé possède une extension .nupkg. NuGet.exe se trouve dans ce package:

  1. Modifier l’extension .nupkg en .zip
  2. Décompresser l’archive zip.
  3. NuGet.exe se trouve dans [Nom du package]/tools/NuGet.exe

En ajoutant le répertoire où se trouve NuGet.exe dans la variable d’environnement PATH, on peut utiliser facilement NuGet.exe dans une invite de commandes.

Avec Chocolatey

Il est possible d’installer l’exécutable NuGet.exe en utilisant Chocolatey. L’intérêt de cette méthode est d’avoir une procédure facilement scriptable dans un script de déploiement (avec Puppet, Ansible ou Chef).

Après avoir installé Chocolatey (https://chocolatey.org/install), il suffit de taper la commande suivante pour installer Nuget.CommandLine:

choco install nuget.commandline

Configuration

Emplacement

La configuration NuGet se trouve dans un ficher XML NuGet.config. Il peut exister plusieurs versions de ce fichier suivant les différentes versions de NuGet et suivant la portée du paramétrage:

  • Dans le répertoire d’un projet, le paramétrage s’appliquera seulement dans le cadre du projet.
  • L’emplacement par défaut est: %APPDATA%\NuGet\NuGet.Config. La portée de ce fichier est globale.
  • A l’échelle de la machine, on peut utiliser un fichier dont la portée sera la machine ou une version particulière de Visual Studio. Ce fichier se trouve dans %ProgramData%\NuGet\Config.

    Suivant la version de Visual Studio le répertoire peut être:

    • %ProgramData%\NuGet\Config\[IDE]\[Version]\[SKU]\*.config
    • %ProgramData%\NuGet\Config\[IDE]\[Version]\*.config
    • %ProgramData%\NuGet\Config\[IDE]\*.config
    • %ProgramData%\NuGet\Config\*.config

    [IDE] correspond à VisualStudio; [Version] correspond à celle de Visual Studio (la version de Visual Studio 2015 est 14.0); [SKU] correspond à Community, Pro ou Enterprise.

Plus de détails sur l’emplacement du fichier de configuration dans Configuring NuGet behavior.

Contenu

La prise en compte de la configuration se fait en commençant par le fichier le plus global (i.e. fichier dans %ProgramData%) et en allant vers le fichier le plus spécifique (par exemple dans le répertoire d’un projet).

Les éléments de configuration sont surchargés par addition, ainsi si on indique des sources dans un fichier global et d’autres sources dans un fichier plus spécifique, les sources seront prises en compte par addition. Pour ne pas avoir ce comportement, il faut utiliser le nœud <clear />.

Par exemple un fichier NuGet.config peut contenir les nœuds suivants:

<?xml version="1.0" encoding="UTF-8"?> 
<configuration> 
    <config> 
        <add key="DefaultPushSource" value="https://example.com/packages/" /> 
    </config> 
    <packageSources> 
        <add key="Example Package Source" value="https://example.com/packages/" /> 
        <add key="nuget.org" value="https://www.nuget.org/api/v2/" /> 
    </packageSources> 
    <disabledPackageSources> 
        <add key="nuget.org" value="true" /> 
    </disabledPackageSources> 
</configuration>

Le détail de la configuration est:

  • Le nœud config permet d’indiquer les repositories vers lesquels on peut uploader des packages (cf. Nuget push).
  • Le nœud packageSources indique les sources à partir desquels les packages peuvent être téléchargés.
  • Le nœud disabledPackageSources contient les sources que l’on souhaite désactiver. Le nom de la source est indiquée avec le clé. Quand le booléen est à true la source est désactivée (c’est-à-dire que les packages ne pourront plus être téléchargés à partir de cette source).

Clear

Dans le nœud packageSources, il est possible d’indiquer <clear />:

<packageSources> 
    <clear />  
    <add key="otherSource" value="https://other/nuget/source" /> 
</packageSources>

<clear /> permet d’indiquer que les sources renseignées dans des fichiers plus haut dans la hiérarchie de prise en compte de la configuration ne seront pas ajoutées. Seulement la source otherSource sera prise en compte.

Sauvegarder une “Api Key”

Il est possible de sauvegarder l’Api Key dans un fichier NuGet.Config pour qu’elle soit automatiquement utilisée, par exemple, lorsqu’on exécute une instruction nuget push. La clé sauvergardée sera cryptée dans le fichier NuGet.Config.
Comme précisé pour plus haut, l’emplacement par défaut du fichier NuGet.Config est: %APPDATA%\NuGet\NuGet.Config (i.e. par exemple: C:\Users\[login utilisateur]\AppData\Roaming\NuGet\NuGet.Config).

Pour sauvegarder l’Api Key dans le fichier NuGet.config de l’utilisateur, il faut exécuter la commande:

nuget SetApiKey [Api Key]

L’Api Key sera alors, ajoutée dans le noeud apikeys du NuGet.Config, par exemple:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<apikeys>
  <add key="https://example.com/packages/" value="EERzfdsfnd8BFdERjHoAwE/Cl+sBAAAAnMGkdu4+rkqpSdQUWwjfIgAAAAACAAAAAAADZgAAwAAAABAAAAA5gG4wxeb8Vn4X0Y0p//OvAAAAAASAAACgAAAAEAAAAF/lDFGgDFfdfdfffgg66jfsdfsfhyyjkfsssUU5UgVgOq+h3t1jw77TGF4DFHJU77Dddg654hEgsSG(yggGDggf6U7hyGTGTgdgdZR4TFfrsghTg==" />
</apikeys>
</configuration>

On peut éditer directement le fichier NuGet.Config pour supprimer une clé.

Configuration dans Visual Studio

Le plus souvent, il n’est pas nécessaire d’éditer les fichiers de configuration de NuGet à la main, il suffit d’aller dans Visual Studio dans:

  1. Cliquer sur le menu Tools puis Options
  2. Etendre le nœud Nuget Package Manager
  3. Sélectionner Package Sources
  4. On peut rajouter des sources en indiquant leur adresse. Il est aussi possible de désactiver des sources particulières.

Télécharger un package

Plusieurs méthodes sont possibles pour télécharger un package avec NuGet. La méthode la plus courante est de le faire avec Visual Studio en utilisant le Package Manager. Toujours dans Visual, si on souhaite ajouter des options particulières, on peut utiliser le Package Manager Console. On peut aussi utiliser NuGet en dehors de l’IDE à la ligne de commandes, avec des outils comme Package Explorer ou directement sur nuget.org.

Informations liées à un package

Pour un package donné, plusieurs informations sont disponibles et visibles à partir du Package Manager, avec Package Explorer ou sur le site nuget.org:

  • Le nom du package
  • La version du package MAJOR.MINOR.PATCH (cf. semantic versioning) suivi éventuellement d’une mention -alpha1 ou -beta1 pour les packages “prerelease”.
    La version d’un package NuGet et la version des assemblies ne correspondent pas forcément

    La version d’un package NuGet peut ne pas correspondre avec la version de ou des assemblies qui s’y trouvent. Il n’y a pas d’obligations que les versions correspondent. Ces différences peuvent mener à des confusions.

  • Les dépendances du package : ce sont les packages nécessaires au package courant. Généralement NuGet télécharge les dépendances quand il télécharge un package.

Dans Visual Studio

Package Manager

Dans Visual Studio, l’intérêt du Package Manager est d’avoir une interface graphique facile  à utiliser. Pour y accéder:

  1. Faire un clique droit sur le projet pour lequel on peut télécharger des packages (il est aussi possible de télécharger des packages à l’échelle de la solution en effectuant un clique droit sur la solution).
  2. Cliquer sur Manage NuGet Packages… (pour une solution, il faut cliquer sur Manager NuGet Packages for Solution…).
  3. L’interface permet de chercher facilement le package qu’on souhaite télécharger

L’interface permet de:

  • Renseigner le nom du package,
  • Indiquer si on souhaite effectuer un nouveau téléchargement (onglet Browse), lister les packages déjà téléchargés (onglet Installed) ou effectuer des mises à jour de packages déjà installés (onglet Updates): en sélectionnant directement le bon onglet, on peut effectuer les étapes plus rapidement.
  • Sélectioner la source à partir de laquelle on veut télécharger le package: si on ne préciser rien, toutes les sources seront prises en compte. Il est parfois plus efficace d’indiquer directement la source quand on la connaît pour que la recherche soit plus rapide.
  • Renseigner la version voulue.
  • Indiquer si on veut une version “prerelease”: dans le cas où cette case n’est pas cochée, les versions “prerelease” n’apparaîtront pas ce qui ce qui peut mener à quelques confusions.
La liste des packages affichés prend en compte la version du framework renseignée dans les paramètres du projet

Si le package n’est compatible qu’avec une version plus récente du framework que celle du projet, il ne sera pas affiché. Ce comportement peut mener à des confusions car on ne verra pas un package qui se trouve bien dans le repository de la source.
On peut s’aider d’outils comme le Package Explorer pour voir la liste des packages sans filtres.

Installation de package au niveau d’une solution

Seules les versions 2.x supportent cette fonctionnalité. Pour les versions ultérieures, il n’est pas possible d’installer un package au niveau d’une solution.

Package Manager Console

Le Package Manager Console permet aussi de télécharger des packages NuGet en utilisant des commandes Powershell. Pour ouvrir le Package Manager Console dans Visual Studio, il faut cliquer sur Tools, sur NuGet Package Manager puis sur Package Manager Console.

Pour que les commandes s’exécutent sur un projet spécifique et pour une source spécifique, il faut le préciser dans l’entête de la console:

Commandes principales de la Package Manager Console

Les commandes les plus courantes sont:
Pour chercher un package (find-package):
A partir de NuGet 3.0, on peut utiliser la commande find-package:

find-package [nom du package]

Pour avoir une version particulière d’un package:

find-package [nom du package] -version [version du package]

Parfois il y a trop de packages qui correspondent pour une recherche, pour restreindre la recherche exactement au nom du package, on peut utiliser l’option -ExactMatch:

find-package [nom du package] -ExactMatch

Pour installer un package (install-package):

Install-package [nom du package] {-Version [numéro de version]}

Préciser la version est facultatif.
Pour une version prérelease:

Install-package [nom du package] {-Version [numéro de version]} -Pre

Pour installer un package en ignorant les dépendances:

Install-package [nom du package] -IgnoreDependencies

Pour lister des packages (get-package):
Lister les packages dans la solution:

get-package {[nom du package]}

Lister les packages disponibles dans les repositories:

get-package {[nom du package]} -ListAvailable

Lister les version d’un package disponible dans les repositories:

get-package [nom du package] -ListAvailable -AllVersions

Pour supprimer un package (uninstall-package):

Uninstall-package [nom du package]

Pour mettre à jour un package (update-package):
Met à jour le package et ses dépendances dans tous les projets:

update-package [nom du package]

Met à jour un package dans un projet particulier:

update-package -ProjectName [nom du projet]

Met à jour tous les packages dans tous les projets:

update-package

Réinstalle un package dans tous les projets:

update-package [nom du package] -reinstall

Examine toutes les assemblies d’un projet et ajoute des binding redirects si nécessaire:

Add-BindingRedirect

Etapes effectuées à l’installation d’un package

Lorsqu’un package est installé dans Visual Studio, il y un certain nombre d’opérations qui sont effectuées sur le projet:

  1. NuGet crée un répertoire packages dans le répertoire de la solution.
  2. Il télécharge le package ainsi que ses dépendances dans le cache de NuGet (cf. emplacement du cache NuGet).
  3. Il décompresse le package ainsi que les dépendances dans le répertoire packages dans le répertoire de la solution. Ce répertoire contiendra les éléments suivants:
    • Dans packages\[{nom du package espacé avec "."}.{version du package}]: se trouve le package .nupkg compressé et le fichier .nuspec contenant les métadonnées du package.
    • Dans packages\[{nom du package espacé avec "."}.{version du package}]\lib: se trouve toutes les assemblies suivant leur target framework. Par exemple pour le framework .NET 4.6.2, le target framework sera net462.
    • Dans packages\[{nom du package espacé avec "."}.{version du package}]\lib\[target framework]: se trouve les assemblies correspondant au target framework.
  4. Il ajoute le fichier packages.config s’il n’existe pas dans le ou les projets où les assemblies provenant du package sont rajoutées. Si packages.config existe, NuGet rajoute les lignes correspondant aux packages rajoutés.
    Ce fichier contient le nom des packages NuGet, leur version et le target framework correspondant. Par exemple, un fichier packages.config peut contenir les informations suivantes:

    <?xml version="1.0" encoding="utf-8"?>
    <packages>
      <package id="MongoDB.Bson" version="2.0.0" targetFramework="net45" />
      <package id="MongoDB.Driver" version="2.0.0" targetFramework="net45" />
      <package id="MongoDB.Driver.Core" version="2.0.0" targetFramework="net45" />
    </packages>
    

Précisions sur le target framework:

  • Pour le framework .NET, target framework sera du type net462, net46, net45, net40 etc…
  • Pour .NET Core: netcore, netcore451 etc…
  • Pour Universal Windows Platform: uap, uap10 etc…
  • Pour .NET Standard: netstandard1.0, netstandard1.6 etc…

On peut trouver une liste exhaustive de ces versions sur : Target Frameworks:

  1. NuGet rajoute les dépendances dans les références du projet (cf. ces références sont visibles dans le répertoire References sur projet dans l’explorateur de solution dans Visual.
  2. NuGet peut exécuter un script Powershell provenant du package s’il y en a un (cette fonctionnalité n’est plus disponible à partir de la version 3.x).
  3. NuGet peut modifier des fichiers de code source, des fichiers de configuration app.config ou web.config (cf. transformations appliquées par NuGet sur des fichiers) par exemple pour rajouter un élément de configuration lié au binding redirect (cf. BindingRedirect en 5min).

Activer la suggestion de packages dans Visual Studio 2017

Cette fonctionnalité est désactivée par défaut et elle n’est disponible que sur Visual Studio 2017. Elle permet de suggérer un package NuGet lorsqu’on écrit un namespace et les objets de ce namespace sont définis dans un package qui n’est pas installé:

Pour activer la fonctionnalité, il faut cliquer dans:

  1. Options du menu Tools
  2. Dans la partie Text Editor -> C# et Advanced
  3. Cocher Suggest using for types in NuGet packages et Suggest usings for types in reference assemblies.

La suggestion de package est accessible au moment de l’édition en plaçant le curseur sur le type inconnue et en tapant Alt + Maj + F10.

Avec Package Explorer

Package Explorer est outil qui permet de gérer des packages NuGet. Le gros intérêt de Package Explorer est qu’il est indépendant de Visual Studio et de la configuration de NuGet dans les fichiers NuGet.config. Il propose une interface simple pour:

  • Parcourir les packages disponibles dans le repository d’une source.
  • Avec accès aux détails d’un package (en particulier les target framework ou les dépendances).
  • Télécharger un package sans tirer toutes les dépendances.
  • Voir le contenu d’un package.
  • Construire un packages.

Package Explorer se trouve sur GitHub et sur CodePlex.

A partir de la ligne de commandes

Pour installer un package dans le répertoire courant:

nuget install [nom du package]

Cette commande ne modifie pas le fichier packages.config ou le fichier du projet.

Quelques options utiles:

  • -PreRelease : autoriser de télécharger une version “pre-release”.
  • -Version [numéro de version]: télécharge une version spécifique.
  • -NoCache: effectue le téléchargement sans utiliser le contenu du répertoire du cache NuGet.
  • -Source [URL de la source]: télécharge le package à partir d’une source précise.

Emplacement du cache

Quand NuGet télécharge des packages, il les place dans un répertoire de cache. Ce cache permet d’éviter d’effectuer des téléchargements du même package quand celui-ci a déjà été installé pour un projet.

Le gros inconvénient de ce cache est qu’il peut mener à des comportements inattendus dans certains cas:

  • Si un package se trouve dans le cache et si il a été supprimé de la source: le package s’installera normalement sur le poste où il est présent dans le cache. En revanche sur une machine où le package n’est pas présent dans le cache, NuGet ne pourra pas l’installer. Il y aura donc, 2 comportements différents sur les 2 machines pour un même package.
  • Si un package a été modifié dans une source mais que la version n’a pas changé: si ce package est déjà présent dans la cache, NuGet utilisera toujours la version qui se trouve dans le cache et non la nouvelle version se trouvant sur la source. Ce comportement entraîne l’utilisation de l’ancien package.

Pour éviter ces comportements, on peut utiliser les options -NoCache lorsqu’on utilise NuGet à la ligne de commande.

On peut vérifier le contenu du cache en exécutant (à partir de la version 3.3):

nuget locals all -list

On peut vider le cache en exécutant (à partir de la version 3.3):

nuget locals all -clear

Pour les versions antérieures à la version 3.3, on peut supprimer le cache directement à partir des répertoires:

  • %LocalAppData%\NuGet\Cache
  • %UserProfile%\.nuget\packages

Creation de package

La création de package se fait au moyen d’un fichier .nuspec qui est un fichier texte indiquant comment générer le package .nupkg et indique des informations sur le package.

Les fichiers ajoutés à un package:

  • peuvent se baser sur d’autres package NuGet, ce sont des dépendances. Ces dépendances seront ajoutées au projet de la même façon que le package lui-même.
  • peuvent être autonomes c’est-à-dire que l’exécution de ces assemblies ne nécessite pas d’autres assemblies ou fichiers.

S’il y a des dépendances sous forme de packages NuGet, il est préférable d’indiquer ces dépendances dans le fichier .nuspec plutôt que d’inclure les assemblies des dépendances directement dans le package que l’on souhaite créer.

Fichier .nuspec

Ce fichier sert à générer un package NuGet, il comprends les fichiers à inclure dans le package et la description du package.

Exemple de fichier .nuspec:

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
  <metadata>
    <id>MyPackage</id>
    <version>2.5.1.23</version>
    <authors>Robert Mitchoum</authors>
    <owners>Robert Mitchoum</owners>
    <licenseUrl>http://opensource.org/licenses/MS-PL</licenseUrl>
    <projectUrl>http://github.com/MyProject</projectUrl>
    <iconUrl>http://github.com/MyProject/nuget_icon.png</iconUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <releaseNotes>Bug fixes and performance improvements</releaseNotes>
    <description>Description of MyPackage</description>
    <copyright>Copyright  ©2016 Mitchoum Corp.</copyright>
    <tags>web utility</tags>
    <dependencies>
        <dependency id="Newtonsoft.Json" version="9.0" />
    </dependencies>
  </metadata>
  <files>
    <file src="readme.txt" target="" />
    <file src="c:\docs\bin\*.xml" target="lib" /> 
    <file src="bin\Debug\*.dll" target="lib" /> 
    <file src="bin\Debug\*.pdb" target="lib" /> 
    <file src="tools\**\*.*" />
    </files>
</package>

Ce fichier comprends les informations suivantes:

  • dans le nœud package\metadata: on indique les informations du package: nom, version, auteurs, description…
  • dans le nœud files\file: on indique où se trouve les fichiers à inclure dans le package. Pour chaque fichier, l’attribut src indique le chemin du fichier à inclure et l’attribut target indique où le fichier sera rangé dans le package NuGet. Le répertoire du fichier dans le package NuGet indiquera quelle sera la fonction du fichier.
  • dans le nœud files\dependencies: on indique quels sont les dépendances NuGet du package à créer. Les dépendances sont reconnues avec le nom du package et des conditions sur sa version.

    Par exemple, on peut indiquer des dépendances de cette façon:

    <dependencies>
      <dependency id="NomPackage1" version="3.0.0" />
      <dependency id="NomPackage2"/>
    </dependencies>
    

    Un syntaxe particulière peut être utilisée pour indiquer les conditions appliquées sur la version des dépendances (cf. Indication de la version des dépendances).

  • dans le nœud frameworkAssemblies\frameworkAssembly: on peut indiquer les assemblies du framework qui sont nécessaires à l’exécution des assemblies du package. Les assemblies du framework ne seront pas inclues dans le package. Ces précisions permettent d’indiquer, par exemple, à quelle version du framework s’applique le package.
    Par exemple:

    <frameworkAssemblies>
      <frameworkAssembly assemblyName="System.ComponentModel.DataAnnotations" targetFramework="net40" />
      <frameworkAssembly assemblyName="System.ServiceModel" targetFramework="net40" />
    </frameworkAssemblies>
    

Nom d’un package

Pour éviter les confusions, il est préférable d’utiliser un nom de package qui n’est pas déjà utilisé même si le package sera utilisé seulement dans un repository privé. Utiliser des noms de package spécifique permettra d’éviter le téléchargement par NuGet de mauvais packages.

Il est préférable d’utiliser des noms de package similaires à ceux des namespaces c’est-à-dire utiliser des “.” plutôt que des “-” ou des “_”.

Version du package

Il est préférable d’utiliser la même version entre celle du package et celle de l’assembly principale du package. Il n’y a pas d’obligation que ces versions soient similaires toutefois, utiliser un numéro de version couplé permet d’éviter des confusions quand le package sera téléchargé et installé.

Indication de la version des dépendances

Les contraintes sur les versions peuvent s’indiquer de cette façon:

1.0 1.0 ≤ x Version 1.0 ou supérieure
(1.0,) 1.0 < x Version strictement supérieure à 1.0
[1.0] x == 1.0 Exactement la version 1.0
(,1.0] x ≤ 1.0 Version 1.0 ou antérieure
(,1.0) x < 1.0 Version strictement antérieure à 1.0
[1.0,2.0] 1.0 ≤ x ≤ 2.0 Version entre la 1.0 et 2.0
(1.0) indication non valide

Pour plus de précisions : Specifying dependency versions for NuGet Packages.

Organisation d’un fichier .nupkg

Précisions sur la fonction d’un fichier suivant son chemin dans un package NuGet:

  • dans le répertoire tools: contient des scripts powershell et des programmes exécutables dans la Package Manager Console.
  • dans le répertoire lib se trouvent les assemblies à inclure au projet, la documentation liée aux assemblies (fichier .xml) et les fichiers symboles (.pdb).
  • dans le répertoire content: ces fichiers seront copiés à la racine du projet Visual dans lequel sera installé le package.
  • dans le répertoire build se trouvent des fichiers de targets ou de propriétés de MSBuild. Ces fichiers sont automatiquement rajoutés au projet Visual.

Comment utiliser un même package pour plusieurs versions de framework ?

A partir du framework .NET 4.0, il est possible d’appliquer plusieurs targets pour un projet de façon à ce qu’il soit déployé sur plusieurs plateformes (par exemple framework .NET 4.0 ou 4.5 ou suivant le .NET Standard 1.6 etc…).

Pour adresser les différents frameworks avec un même package, il suffit de placer les différentes assemblies dans des répertoires suivant une structure avec la version du framework.

Par exemple, si on veut supporter le framework .NET 4.6.2 et .NET Standard 1.6, il faut placer les assemblies suivant la structure:

\lib
    \net462
        \Assembly.dll
    \netstandard1.6
        \Assembly.dll

Si une même assembly est utilisée pour 2 target platforms, il faut obligatoirement copier cette assembly dans les 2 répertoires correspondant à ces target platforms.

Le nom des répertoires des target platforms (par exemple net462 et netstandard1.6) doit respecter une convention permettant d’indiquer précisément une plateforme.

Les plateformes les plus courantes sont :

Framework Abréviation Target framework moniker
.NET framework net net11
net40
net45
net451
net452
.NET Core App netcoreapp netcoreapp1.0
netcoreapp1.1
.NET Core netcore netcore [netcore45]
netcore45 [win, win8]
netcore451 [win81]
netcore50
Universal Windows Platform uap uap [uap10.0]
uap10.0
.NET Standard netstandard netstandard1.0
netstandard1.3
netstandard1.6

On peut trouver une liste exhaustive des target platforms sur Target frameworks.

Il ne faut pas confondre .NET Core App et .NET Core

NET Core App correspond à la première version du .NET Core qui a été renommé en janvier 2016 pour passer de .NET Core 5 à .NET Core 1.0 (voir Introducing .NET Core 1.0).
Pour les versions actuelles de .NET Core, il faut utiliser les abréviations netcoreapp.

Générer un fichier .nuspec

On peut créer un fichier .nuspec directement à la main avec un éditeur de texte mais il est aussi possible de le générer.

Pour générer un fichier générique avec les nœuds XML:

nuget spec [nom du package]

Pour générer un .nuspec à partir d’une assembly:

nuget spec [chemin de l'assembly]

Dans ce cas les informations du fichier seront complétées en fonction des informations de l’assembly.

Pour générer un .nuspec à partir de Visual Studio, il faut se placer dans le répertoire du projet (i.e. du fichier .csproj) et exécuter:

nuget spec

Le fichier généré sera un template contenant des tokens qui seront remplacés par les valeurs à la création du package. Pour que les tokens soient remplacés par les valeurs, il faut que le fichier .nupkg soit généré avec nuget pack [chemin du fichier .csproj].

Ajouter un fichier README

Le fichier sera affiché dans Visual Studio à l’installation du package.
Il suffit d’indiquer le chemin du fichier dans le nœud package\files, le nom du fichier doit être readme.txt:

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
    <!-- ... -->
    <files>
      <file src="readme.txt" target="" />
    </files>
</package>

Ajouter des propriétés et des targets MSBuild

Ajouter des targets ou des propriétés MSBuild dans un package permet de rajouter ces fichiers directement dans un répertoire \build d’un projet. Ces fichiers doivent s’appeler:

  • [nom du package].targets pour les targets,
  • [nom du package].props pour les propriétés.

Si ces fichiers se trouvent dans le répertoire build, ils seront ajoutés pour tous les projets pour lesquels on installe la package quelque soit la version du framework cible. Si on souhaite que les fichiers soient installés pour des frameworks cible spécifiques, il faut ranger les fichiers dans un répertoire utilisant le nom de la plateforme cible.

Par exemple, si les fichiers doivent être installés pour des projets ayant pour plateforme cible le framework .NET 4.5, il faudra placer les fichiers suivant la hiérarchie:

  • build\net45\[nom du package].props et
  • build\net45\[nom du package].targets.

Il faut inclure ensuite des indications sur ces fichiers dans le fichier .nuspec au moment de la création du package.

Suivants les versions de NuGet, le comportement sera différent à l’installation d’un package lorsque celui-ci comprends des targets ou des propriétés MSBuild:

  • pour les versions Nuget 2.x: NuGet rajoute un nœud <Import> dans le fichier .csproj pour inclure les targets et propriétés.
  • pour les versions Nuget 3.x: NuGet ne rajoute pas les “targets” dans le fichier .csproj.

Créer un package .nupkg

Pour créer un package avec le fichier .nuspec:

nuget pack [fichier .nuspec]

Pour créer un package sur un projet Visual Studio:

nuget pack [nom du projet .csproj]

Quelques options peuvent être utiles:

  • -IncludeReferencedProjects: si un projet dépend d’autres projets, cette option permettra d’inclure dans le package, les fichiers générés par les autres projets. Cette option s’utilise en exécutant:
    nuget pack [chemin du fichier .csproj] -IncludeReferencedProjects
    
  • -properties: permet d’utiliser les fichiers provenant d’une configuration de build particulière. Par défaut, nuget pack [chemin du .csproj] utilise la configuration de build par défaut, on peut préciser une configuration spécifique en écrivant:
    nuget pack [chemin du fichier .csproj] -properties Configuration=[nom de la configuration de build]
    

    La configuration de build peut être, par exemple, Release ou Debug.

  • -symbols: cette option permet d’inclure dans le package généré les fichiers .pdb. Elle s’utilise en exécutant:
    nuget pack [nom du projet .csproj] -symbols
    

Nuget push

Permet d’uploader un package sur une source:

nuget push [chemin du fichier .nupkg] -Source [URL de la source]

On peut omettre l’option -Source à partir de NuGet 3.4.2 si on précise une valeur DefaultPushSource dans NuGet.config.

L’authentification auprès de la source se fait en utilisant une Api Key. Cette Api Key est fournie par la source. Avec l’Api Key:

nuget push [chemin du fichier .nupkg] [ApiKey de la source] -Source [URL de la source]

On peut aussi ajouter l’Api Key en configuration pour ne pas avoir à la préciser à chaque exécution de nuget push (cf. Sauvegarder une “Api Key”).

Modifier des fichiers du projet à l’installation du package

A partir de NuGet 3.x, on ne peut plus inclure des scripts d’installation Powershell dans un package NuGet. Il existe, en revanche, des méthodes pour créer ou modifier des fichiers dans un projet Visual.

Les modifications à appliquer sur les fichiers seront effectuées à l’installation du package et quand on désinstallera le package, certaines de ces modifications peuvent être annulées.

Modifier un fichier de code source

Les modifications peuvent être appliquées au projet à l’installation mais elles ne seront pas annulées à la désinstallation.

Il faut effectuer les étapes suivantes:

  • Pour ajouter un fichier dans un répertoire: par exemple pour ajouter le fichier dans le répertoire Controller, il faut placer le fichier dans le répertoire content\Controller du package NuGet.
  • Le nom du fichier doit comporter le suffixe .pp pour indiquer que le fichier doit être modifié à l’installation.

    Par exemple si on place un fichier ProductController.cs.pp dans le répertoire content\Controller du package NuGet, le fichier Controller\ProductController.cs sera ajouté dans le projet Visual.

  • Le contenu du fichier avec l’extension .pp peut comporter des tokens indiqués sous la forme $[nom du "token"]$ qui seront remplacés par leur valeur à l’installation.
    Par exemple : si on place la ligne : namespace $RootNamespace$.Controllers dans le fichier avec l’extension .pp et le RootNamespace est ProductApi dans le projet, le résultat après installation sera:

    namespace ProductApi.Controllers
    

    On trouver une la liste exhaustive des tokens utilisables dans ProjectProperties.

Modifier un fichier de configuration

Les modifications apportées à ces fichiers peuvent être annulées à la désinstallation.
2 méthodes sont possibles:

  • Appliquer une transformation XML,
  • Utiliser un fichier XDT.

Appliquer une transformation XML
Pour modifier un fichier de configuration App.config ou Web.config, il faut:

  • Ajouter le suffixe .transform au nom du fichier à modifier.
    Par exemple : pour un fichier App.config, il faut renommer le fichier en App.config.transform.
  • Placer ce fichier dans le répertoire content du package NuGet.
  • Ajouter des nœuds XML <add ... /> pour ajouter les éléments dans le fichier final.
    Par exemple : si on écrit dans le fichier Web.config.transform:

    <configuration>
      <system.webServer>
        <nodeToAdd value="false" />
        <modules>
          <add name="module1" type="Example.module1, Example" />
          <add name="module2" type="Example.module2, Example" />
        </modules>
      </system.webServer>
      <customNode>
        <!-- Custom text -->
        <innerCustomNode allowRemoteAccess="false" />
      </customNode>
    </configuration>
    

Dans le fichier Web.config:

  • Le nœud configuration/system.webServer/nodeToAdd sera rajouté.
  • Les nœuds configuration/system.webServer/nodeToAdd/modules/<add name="module1"/> et <add name="module2" />
  • Les commentaires <!-- Custom text --> seront ajoutés en suivant la hiérarchie XML.
  • etc…

A la désintallation du package, ces modifications sont annulées seulement si les lignes ajoutées n’ont pas été modifiées après l’installation.

Appliquer une modification par fichier XDT
Cette fonctionnalité est disponible à partir de NuGet 2.6.
On peut appliquer des transformations à un fichier XML en utilisant la syntae XDT. Pour plus de détails, voir Web.config Transformation Syntax for Web Application Project Deployment Using Visual Studio.

Pour appliquer ces modifications, il faut:

  • Ajouter le suffixe .install.xdt au nom du fichier à modifier.

    Par exemple : pour un fichier App.config, il faut renommer le fichier en App.config.install.xdt.

  • Placer ce fichier dans le répertoire content du package NuGet.
  • On peut utiliser des tokens indiqués sous la forme $[nom du "token"]$ qui seront remplacés par leur valeur à l’installation (voir ProjectProperties pour la liste des tokens).

Par exemple, si on utilise le fichier Web.config.install.xdt:

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <system.webServer>
    <nodeToAdd value="false" xdt:Transform="Insert"/>
    <modules>
      <add name="module1" type="Example.module1, Example" xdt:Transform="Insert"/>
      <add name="module2" type="Example.module2, Example" xdt:Transform="Insert"/>
    </modules>
  </system.webServer>
  <customNode>
    <innerCustomNode allowRemoteAccess="false" xdt:Transform="Insert"/>
  </customNode>
</configuration>

Les mêmes modifications seront appliquées au fichier Web.config d’origine que l’exemple précédent.

Pour que les modifications soient annulées à la désintallation, il faut ajouter au package NuGet un fichier avec l’extension .uninstall.xdt.

Par exemple, pour annuler les modifications précédentes, on peut ajouter un fichier Web.config.uninstall.xdt avec le contenu:

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <system.webServer>
    <nodeToAdd value="false" xdt:Transform="Remove"/>
    <modules>
      <add name="module1" type="Example.module1, Example" xdt:Transform="Remove"/>
      <add name="module2" type="Example.module2, Example" xdt:Transform="Remove"/>
    </modules>
  </system.webServer>
  <customNode>
    <innerCustomNode allowRemoteAccess="false" xdt:Transform="Remove"/>
  </customNode>
</configuration>

Appliquer un script d’installation Powershell

Cette fonctionnalité n’est plus disponible à partir de NuGet 3.x. Elle permet d’exécuter un script Powershell à l’installation et la désinstallation d’un package NuGet.

Pour que ces scripts soient exécutés, il faut qu’ils soient nommés suivant la convention suivante:

  • Init.ps1: il est exécuté à la 1ère installation du package,
  • Install.ps1: ce script est exécuté à l’installation du package,
  • Uninstall.ps1: il est exécuté à la désinstallation du package.

Il faut placer ses scripts dans le répertoire tools du package NuGet.

Le script Powershell doit commencer avec la ligne:

param($installPath, $toolsPath, $package, $project)

avec:

  • $installPath: path où le projet se trouve.
  • $toolsPath: path où le contenu du répertoire tools est décompressé à l’installation.
  • $package: informations sur le package qui est installé.
  • $project: informations sur le projet dans lequel l’installation est effectuée. Ces informations sont de type EnvDTE.

Nuget restore

Nuget restore est une fonctionnalité qui permet d’ajouter les assemblies provenant de packages NuGet dans les projets d’une solution juste avant la compilation. Si ces packages n’ont pas été téléchargés. NuGet les télécharge, les décompresse et les ajoute aux projets en fonction du fichier packages.config de chaque projet.

Nuget restore peut aussi restaurer dans le projet des packages si certains sont manquants.

L’intérêt de cette fonctionnalité est l’ajout automatique des packages sans que le développeur ne s’en préoccupe.
3 méthodes existent pour activer la fonctionnalité restore:

  • au niveau de Visual Studio: à partir de Nuget 2.7.
  • au niveau de MSBuild: pour les versions antérieures à Nuget 2.6.
  • en appelant une commande à la ligne de commandes.

Activer la fonctionnalité

Avec Visual Studio

Pour activer Nuget restore dans Visual studio: Tools -> Options -> Nuget package Manager -> General

Il faut activer Allow Nuget to download missing package.

L’option Automatically check for missing packages during build in Visual Studio permet d’effectuer le vérification des packages à chaque build.

Avec les fichiers de configuration

Au niveau global:
Il faut modifier %AppData%\Nuget\Nuget.config:

<configuration>
  <packageRestore>
    <add key="enabled" value="False" />
  </packageRestore>
</configuration>

Avant Nuget 2.6, il faut effectuer la modification dans .nuget\nuget.config dans chaque projet.

Pour vérifier la présence des packages à chaque build, il faut modifier le fichier: %AppData%\Nuget\Nuget.config:

<configuration>
  <packageRestore>
    <add key="automatic" value="False" />
  </packageRestore>
</configuration>

L’activation de ces options peuvent être globale en modifiant les fichiers dans:

%ProgramData%\Nuget\Config\[IDE]\[Version]\[SKU]

On peut aussi utiliser la variable d’environnement EnableNuGetPackageRestore en affectant la valeur true ou false pour surcharger les paramètres indiqués dans les fichiers de configuration. La valeur de la variable d’environnement sera utilisée par Visual Studio à condition qu’elle soit affectée avant le démarrage.

La priorité des fichiers de configuration se fait dans l’ordre indiqué précédemment.

Activer Nuget restore au niveau de MSBuild

Nuget restore existe sous cette forme pour les versions précédant Nuget 2.6. Les versions suivant Nuget 2.7 sont compatibles avec ce paramétrage toutefois il est déconseillé de l’utiliser.

L’activation se fait dans Visual Studio en effectuant un clique droit sur la solution et en sélectionnant Enable Nuget Package Restore.

A l’activation de cette option:

  • NuGet crée un répertoire .nuget au niveau de la solution et y ajoute Nuget.exe, un fichier nuget.config et un fichier nuget.targets.
  • NuGet met à jour tous les projets en ajoutant un nœud <RestorePackages>true<RestorePackages> et importe les targets se trouvant dans nuget.targets.
Breaking changes entre NuGet 2.6 et 2.7

Le paramétrage de Nuget restore au niveau de MSBuild pour les versions précédant Nuget 2.6 est incompatible avec les versions 2.7 et suivantes et peut mener à des comportements inattendus.

Quand Nuget restore est activée au niveau de MSBuild, Nuget 2.6 et précédents crée un répertoire .nuget avec un exécutable de Nuget.exe, un fichier Nuget.config et un fichier Nuget.targets. Avec Nuget 2.7 et suivant, la présence du répertoire .nuget peut causer ndes erreurs car la version de Nuget.exe correspondra à une ancienne version.

D’autre part si il existe un fichier .nuget\Nuget.targets dans le répertoire d’un projet, la restauration automatique (activée au niveau de Visual studio) sera ignorée pour ces projets.

Pour passer de Nuget restore au niveau de MSBuild à la restauration automatique, il faut d’abord d’abords supprimer tous les répertoires .nuget se trouvant dans les répertoires des projets et de la solution.

Il faut ensuite éditer les fichiers .csproj en supprimant les nœuds <RestorePackages> et supprimer toutes les références aux fichiers .nuget.targets.

Étapes effectuées par NuGet lorsque la restauration automatique est activée

Si NuGet restore est activée au niveau de Visual Studio:

  • un fichier .nuget\nuget.config est créé,
  • avant la compilation proprement dite, NuGet parcours tous les fichiers packages.config pour télécharger les packages à partir du cache ou à partir de la source.

Restauration automatique à partir de la ligne de commandes

Pour les versions 2.7 et suivantes, on peut exécuter Nuget restore au niveau d’une solution en exécutant dans le répertoire de la solution:

nuget restore

Ou

nuget restore [fichier .sln]
Références:
  • Repository nuget: https://www.nuget.org/
  • Extension NuGet Package Manager pour Visual Studio: https://marketplace.visualstudio.com/items?itemName=NuGetTeam.NuGetPackageManager
  • Consume NuGet packages in Visual Studio: https://www.visualstudio.com/en-us/docs/package/nuget/consume
  • Configuring NuGet behavior: https://docs.microsoft.com/fr-fr/nuget/consume-packages/configuring-nuget-behavior
  • NuGet File Locations: http://lastexitcode.com/projects/NuGet/FileLocations/
  • Target frameworks: https://docs.microsoft.com/en-us/nuget/schema/target-frameworks
  • NuGet Package Manager UI: https://docs.microsoft.com/en-us/nuget/tools/package-manager-ui
  • Installing NuGet: https://docs.microsoft.com/fr-fr/nuget/guides/install-nuget
  • Release Notes NuGet: https://docs.microsoft.com/en-us/nuget/release-notes/index
  • Creating NuGet packages: https://docs.microsoft.com/en-us/nuget/create-packages/creating-a-package
  • Installing and reinstalling packages with package restore: https://docs.microsoft.com/en-us/nuget/consume-packages/package-restore
  • Transforming source code and configuration files: https://docs.microsoft.com/en-us/nuget/create-packages/source-and-config-file-transformations
  • Supporting multiple .NET framework versions: https://docs.microsoft.com/en-us/nuget/create-packages/supporting-multiple-target-frameworks
  • NuGet CLI reference: https://docs.microsoft.com/fr-fr/nuget/tools/nuget-exe-cli-reference
  • NuGet.VisualStudio 4.0.0 : https://www.nuget.org/packages/NuGet.VisualStudio
  • Visual Studio 2017 can automatically recommend NuGet packages for unknown types: https://www.hanselman.com/blog/VisualStudio2017CanAutomaticallyRecommendNuGetPackagesForUnknownTypes.aspx
  • ASP.NET 5 is dead – Introducing ASP.NET Core 1.0 and .NET Core 1.0: https://www.hanselman.com/blog/ASPNET5IsDeadIntroducingASPNETCore10AndNETCore10.aspx
  • Installing Chocolatey: https://chocolatey.org/install
  • Nuget.CommandLine 3.5.0 with Chocolatey: https://chocolatey.org/packages/NuGet.CommandLine
  • Running PowerShell scripts during NuGet package installation and removal: https://everydaylifein.net/netframework/running-powershell-scripts-during-nuget-package-installation-and-removal.html
  • NuGet Package explorer sur Github: https://github.com/NuGetPackageExplorer/NuGetPackageExplorer
  • Add NuGet package without its dependencies on Stackoverflow: https://stackoverflow.com/questions/9792864/add-nuget-package-without-its-dependencies
  • Saving your API key with nuget.exe: http://blog.davidebbo.com/2011/03/saving-your-api-key-with-nugetexe.html
  • Leave a Reply