Dotnet Core et ses templates CLI, pourquoi s’arrêter à C# ou peut-être pas?

Dotnet Core et ses templates CLI, pourquoi s’arrêter à C# ou peut-être pas?

2018-10-30 0 By Nordes

Comme le titre l’indique, pourquoi s’arrêter à un template et pourquoi devrait-on, ou pas, faire que des templates C#?

Afin de répondre à cette question, il faut tout d’abord créer un template ou s’inspirer d’un existant. Notez qu’il est possible de créer des packets contenant plusieurs templates à la fois.

Comment créer un template .Net (core ou pas, c’est pas grave)

Pour débuter, on va faire ça simple. Créons un petit template C# dotnet avec rien de bien intéressant à l’intérieur a part peut être un pre-setting pour un album photo (Connection BD + Script de migration entity framework). Dans cet article, nous n’allons pas bâtir l’application, mais seulement expliquer les principes et le packaging.

Par exemple, vous pouriez faire dotnet new mvcet terminer le reste de votre projet de base (template). Ensuite, il afin de transformer ce projet en template, vous aurez à créer un répertoire spécial nommé .template.config qui se situe dans votre répertoire de projet. Ce fichier respecte doit respecter les standards Microsoft (disponible sur le site MSDN si vous cherchez un peu).

Ici par exemple vous pouriez avoir ce qui suit (Vous pouvez adapter à bon vous semble ;)):

{
  "$schema": "http://json.schemastore.org/template",
  "author": "Nordes Menard-Lamarre",
  "classifications": [ "MVC", "PhotoGallery" ],
  "groupIdentity": "HoNoSoFt.DotNet.Web.Templates.Gallery",
  "identity": "HoNoSoFt.Gallery",
  "name": "Ce qui s'affiche dans la description",
  "preferNameDirectory": true,
  "primaryOutputs": [
    {
      "path": "HoNoSoFt.Gallery.csproj"
    }
  ],
  "shortName": "honosoft-gallery",
  "sourceName": "HoNoSoFt.Gallery",
  "sources": [
    {
      "source": "./",
      "target": "./",
      "exclude": [
        ".template.config/**"
      ],
      "modifiers": [
        {
          "condition": "(TargetFrameworkOverride == '')",
          "exclude": [
            "app.config"
          ]
        },
        {
          "condition": "(ExcludeLaunchSettings)",
          "exclude": [
            "Properties/launchSettings.json"
          ]
        }
      ]
    }
  ],
  "symbols": {
    "ExcludeLaunchSettings": {
      "type": "parameter",
      "datatype": "bool",
      "defaultValue": "false",
      "description": "Whether to exclude launchSettings.json from the generated template."
    },
    "HttpPort": {
      "type": "parameter",
      "datatype": "integer",
      "description": "Port number to use for the HTTP endpoint in launchSettings.json."
    },
    "HttpPortGenerated": {
      "type": "generated",
      "generator": "port"
    },
    "HttpPortReplacer": {
      "type": "generated",
      "generator": "coalesce",
      "parameters": {
        "sourceVariableName": "HttpPort",
        "fallbackVariableName": "HttpPortGenerated"
      },
      "replaces": "8080"
    },
    "HttpsPort": {
      "type": "parameter",
      "datatype": "integer",
      "description": "Port number to use for the HTTPS endpoint in launchSettings.json. This option is only applicable when the parameter no-https is not used (no-https will be ignored if either IndividualAuth or OrganizationalAuth is used)."
    },
    "HttpsPortGenerated": {
      "type": "generated",
      "generator": "port",
      "parameters": {
        "low": 44300,
        "high": 44399
      }
    },
    "HttpsPortReplacer": {
      "type": "generated",
      "generator": "coalesce",
      "parameters": {
        "sourceVariableName": "HttpsPort",
        "fallbackVariableName": "HttpsPortGenerated"
      },
      "replaces": "44300"
    },
    "TargetFrameworkOverride": {
      "type": "parameter",
      "description": "Overrides the target framework",
      "replaces": "TargetFrameworkOverride",
      "datatype": "string",
      "defaultValue": ""
    },
    "Framework": {
      "type": "parameter",
      "description": "The target framework for the project.",
      "datatype": "choice",
      "choices": [
        {
          "choice": "netcoreapp2.1",
          "description": "Target netcoreapp2.1"
        }
      ],
      "replaces": "netcoreapp2.1",
      "defaultValue": "netcoreapp2.1"
    },
    "HostIdentifier": {
      "type": "bind",
      "binding": "HostIdentifier"
    },
    "skipRestore": {
      "type": "parameter",
      "datatype": "bool",
      "description": "If specified, skips the automatic restore of the project on create.",
      "defaultValue": "false"
    },
    "NoHttps": {
      "type": "parameter",
      "datatype": "bool",
      "defaultValue": "false",
      "description": "Whether to turn off HTTPS. This option only applies if Individual, IndividualB2C, SingleOrg, or MultiOrg aren't used for --auth."
    }
  },
  "tags": {
    "language": "C#",
    "type": "project"
  },


  "precedence": 100,
  "guids": [
      "6B3E8EE8-92E3-41CE-A356-A5F880EEA367"
  ],
  "postActions": [
      {
        "condition": "(!skipRestore)",
        "description": "Restore NuGet packages required by this project.",
        "manualInstructions": [
          {
            "text": "Run 'dotnet restore'"
          }
        ],
        "actionId": "210D431B-A78B-4D2F-B762-4ED3E3EA9025",
        "continueOnError": true
      }
    ]
}

Une fois ce fichier sauvegardé, ce n’est pas terminé. Vous devrez créer votre fichier “nuspec”. C’est possible de le créer à partir de Visual Studio, ou si vous avez la flemme, de le créer aussi manuellement. Dans tous les cas, vous devrez télécharger une version de nuget en ligne de commande.

Exemple de fichier nuspec (Aussi très bien documenté sur le site de MSDN):

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
  <metadata>
    <id>HoNoSoFt.DotNet.Web.Spa.ProjectTemplates</id>
    <authors>Nordes Menard-Lamarre</authors>
    <description>
      La description qui apparaitra sur le site de Nuget.org
    </description>
    <packageTypes>
      <packageType name="Template" />
    </packageTypes>
    <version>{{version}}</version>
    <iconUrl>https://www.honosoft.com/img/logo.png</iconUrl>
    <projectUrl>https://github.com/votre_nom/Votre.ProjectTemplates</projectUrl>
    <licenseUrl>https://github.com/votre_nom/Votre.ProjectTemplates/blob/master/LICENSE</licenseUrl>
  </metadata>
  <files>
    <file
      src="HoNoSoFt.Gallery.CSharp/**/*"
      exclude="**/node_modules/**;**/package-lock.json;**/bin/**;**/obj/**;**/.vs/**;**/.vscode/**;**/wwwroot/**"
      target="Content" />
  </files>
</package>

Ici concernant les fichiers, vous n’être absolument pas obligé d’avoir une configuration fichier par template. Si vous voulez vous simplifier la vie, vous pouvez simplement vous créer un répertoire “Contenu” et y mettre vos projets templates en C#. Ceci-dit, une fois complété, pour créer votre package “nupkg“, vous devrez lancer la ligne de commande avec nuget.

La commande est (à partir de votre répertoire nuspec) : nuget pack. Avant de lancer la commande, n’oubliez pas de mettre à jour votre numéro de {{version}}. Cette version doit être sous le standard Majeur.Mineur.Build.

Afin de tester votre template vous pourrez ensuite l’installer en effectuant: dotnet new -i votre.fichier.nupkg. Et pour voir si c’est bien installé, n’oubliez pas que vous pouvez aussi lister votre projet à l’aide de la commande dotnet new -l. Une fois que vous êtes certain que votre template est présent, vous pouvez créer un répertoire “temporaire” et tester l’initialization de votre template. La commande cette fois sera dotnet new votre-nom-de-templateet les options par défauts seront utilisées (Voir le template.json créer plus tôt).

Et si on veut ajouter d’autres templates en même temps?

Oui, c’est possible. Vous pouvez soit ajouter d’autre répertoire dans la liste des fichiers (balise files qui est dans le nuspec) ou bien si vous avez opté pour un répertoire plus global, comme “Contenu”, vous n’avez qu’à créer d’autres projets avec le répertoire .template.config. Cependant, il y a un point important. Et ce point est que vous devez impérativement avoir un nom différent dans le GroupIdentity du fichier template.json. Sinon, si vous voulez utiliser le même nom, vous devrez combiner avec des options (voir les détails du schéma)

Est-ce possible de créer des template non C# ou Microsoft

Je crois que c’est tout à fait possible et ce sera sans doute ce que je ferai dans l’avenir. J’aime bien travailler avec node pour des PoC et je crois que d’utiliser dotnet new avec les templates va faciliter le fait d’utiliser ou non un backend.

Exemple réel

Récemment, j’ai travailler sur un projet personnel qui crée un Template Dotnet Core 2.1 + VueJS + Picnic CSS + beaucoup d’autres trucs. Ce template est disponible sur https://github.com/nordes/HoNoSoFt.DotNet.Web.Spa.ProjectTemplates et vous pouvez aussi voir comment j’ai intégrer le tout avec AppVeyor pour les build automatisé et le déploiement automatique de l’artifact NuGet sur nuget.org.

Tous les détails afin d’utiliser les templates sont disponible sur le site Github ou bien sur la section Wiki de Github.

Bon coding!

Nordès