Création et déploiement d'une application ASP.NET Core sous Linux

Avec Entity Framework Core, VS Code et Docker

Vous découvrirez dans cet article comment créer et déployer une application ASP.NET Core sous Linux avec Entity Framework Core, VS Code, NGINX et Docker.

Article lu   fois.

L'auteur

Site personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Introduction

Microsoft a rendu open source et multiplateforme .NET Core pour permettre aux développeurs utilisant Linux ou OS X d'exploiter sa plateforme de développement pour créer des applications .NET multiplateformes.

Depuis la sortie de .NET Core en version stable, de nombreuses personnes m'ont déjà posé la question à savoir s'il était possible de créer et déployer un site Web pro avec ASP.NET Core sous un système d'exploitation Linux.

À ce jour, il existe de nombreux outils open source permettant de mettre en place une application .NET Core sous Linux. De plus, il y a déjà plusieurs tutoriels sur Internet sur le développement avec .NET Core.

On va regretter toutefois que ceux-ci soient beaucoup plus centrés sur Windows. Néanmoins, en dehors de l'installation et la configuration des outils qui changent, l'écriture du code reste pareille.

Dans ce tutoriel, nous verrons comment mettre en place et déployer une application ASP.NET Core sous Linux. Je vais utiliser Ubuntu 16.04 LTS.

II. Prérequis

Cet article ne nécessite pas de connaissances avancées en programmation. Mais, un minimum en développement Web et plus spécifiquement en ASP.NET MVC est nécessaire pour sa bonne compréhension.

Nous allons utiliser les outils suivants :

  • .NET Core ;
  • Visual Studio Code ;
  • le générateur Yeoman ;
  • un navigateur (Firefox, Chrome, etc.) ;
  • NGINX ;
  • Docker.

III. Présentation et installation des outils

III-A. ASP.NET Core

III-A-1. Description

ASP.NET Core est un Framework multiplateforme permettant de développer des applications Web. Il permet de développer des applications MVC, des APIs Web et bien plus.

ASP.NET Core est bâti sur la modularité pour permettre de développer des applications optimisées pour le Cloud. Ainsi, il offre un modèle flexible permettant de déployer son application avec le minimum requis pour son exécution.

III-A-2. Installation

ASP.NET Core est livré avec .NET Core. Pour disposer du framework, vous devez simplement installer ce dernier. Pour la rédaction de cet article, j'ai utilisé la version 1.0.x de .NET Core. Il s'agit de la version bénéficiant d'un support LTS (Long Term Support) de la part de Microsoft.

Exécutez dans un premier temps les commandes suivantes, pour mettre à jour apt-get et prendre en compte l'emplacement ou est disponible le package dont nous avons besoin :

 
Sélectionnez
sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet-release/ xenial main" > /etc/apt/sources.list.d/dotnetdev.list'
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 417A0893
sudo apt-get update

Exécutez ensuite la commande suivante pour installer .NET Core :

 
Sélectionnez
sudo apt-get install dotnet-dev-1.0.0-preview3-004056
Image non disponible


Pour vérifier que votre installation s'est effectuée correctement, exécutez successivement les commandes suivantes :

 
Sélectionnez
mkdir testapp
cd testapp
dotnet new
dotnet restore
dotnet run

Pour rappel :

  • Mkdir testapp va permettre de créer un nouveau dossier testapp ;
  • Cd testapp va permettre de changer de répertoire pour le répertoire testapp ;
  • Dotnet new va créer dans le répertoire testapp un nouveau projet C# de type console ;
  • Dotnet restore va utiliser NuGet pour restaurer l'ensemble des packages nécessaires pour exécuter votre application ;
  • Dotnet run va lancer l'application, et vous aurez le résultat suivant :
Image non disponible

III-B. Visual Studio Code

III-B-1. Présentation

Visual Studio Code est développé en open source par Microsoft et offre aux développeurs le nécessaire (coloration syntaxique, IntelliSence, débogage) pour créer des applications en utilisant l'OS de leur choix (Windows, Linux ou Mac).

Visual Studio Code supporte de nombreux langages de programmation. Celui-ci évolue assez rapidement avec des mises à jour fréquentes. De plus, le support de la communauté permet à sa galerie d'extensions de grandir rapidement et offrir une panoplie d'outils pour étendre les fonctionnalités de l'EDI.

III-B-2. Installation de Visual Studio Code

Vous devez télécharger l'outil à l'adresse suivante, en choisissant la version correspondante à votre OS : https://code.visualstudio.com/Download

Double cliquez sur le fichier pour l'installer, ou exécutez la commande suivante dans le terminal :

 
Sélectionnez
sudo dpkg -i <file>.deb

Ceci fait, vous devez installer l'extension « C# for Visual Studio Code ». Cette extension va permettre d'ajouter la prise en charge du langage C# à l'éditeur de code. Pour l'installer :

  • cliquez sur le menu View, puis sur Extensions ;
  • dans la fenêtre qui va s'afficher, saisissez dans la barre de recherche c# ;
  • cliquez sur Install pour procéder à l'installation de ce dernier.
 
Image non disponible

III-C. Yeoman

III-C-1. Description

Pour créer notre application qui servira d'exemple, nous allons utiliser Yeoman. Yeoman est un outil open source qui permet d'avoir à porter de main les nombreux modèles de projets qui sont disponibles dans Visual Studio. Avec cet outil, en une commande, vous pouvez générer votre projet avec les fichiers correspondant au template que vous avez choisi.

III-C-2. Installation

Yeoman nécessite le gestionnaire de packages Node.js (npm). Vous devez donc installer Node.js. Pour le faire , vous pouvez utiliser les commandes suivantes sous Linux :

 
Sélectionnez
curl -sL https://deb.nodesource.com/setup_4.x 
sudo -E bash -
sudo apt-get install -y nodejs

Ceci fait, vous pouvez exécuter la commande suivante pour vérifier que l'installation s'est effectuée correctement :

 
Sélectionnez
node --version && npm --version

Pour installer Yeoman et bower, exécutez la commande suivante :

 
Sélectionnez
npm install -g yo bower

Exécutez la commande suivante pour installer le générateur Yeoman pour les projets .NET Core :

 
Sélectionnez
npm install -g generator-aspnet

IV. Création du projet

Exécutez les commandes suivantes pour créer le répertoire des projets :

 
Sélectionnez
mkdir projects
cd projects

Ceci fait, vous allez exécuter la commande suivante pour créer le projet :

 
Sélectionnez
yo aspnet

Le générateur Yeoman va afficher un menu, avec différents  modèles de projet. Sélectionnez  Web Application Basic [Without Membership and Authorization] :

Image non disponible

À l'étape suivante, sélectionnez Bootstrap comme framework d'interface utilisateur :

Image non disponible

Pour le nom de l'application, saisissez SampleApp et validez. Dans le dossier Projects, un nouveau dossier SampleApp sera créé avec les fichiers de votre application.

 

Saisissez la commande suivante pour vous positionner dans le dossier du projet :

 
 
Sélectionnez
Cd sampleapp

Pour exécuter l'application, vous allez effectuer les deux commandes suivantes :

 
Sélectionnez
Dotnet restore
Dotnet run
Image non disponible

Ouvrez votre navigateur et saisissez le lien ci-dessus dans ce dernier. Vous obtiendrez la page suivante, qui est la page d'accueil de votre application.

Image non disponible

L'application est exécutée en utilisant par défaut le serveur Web Kestrel. Ce dernier est un serveur web léger et open source, basé sur libuv. Il s'agit d'une alternative open source a IIS, pour l'exécution d'applications ASP.NET Core sur Windows, Linux et OS X.

Lorsque le serveur web est démarré, il affiche dans le terminal les logs de votre application : exceptions, détails des appels, etc. lorsque cette dernière est en cours d'exécution.

Image non disponible

Arrêtez l'exécution du serveur Web en utilisant la combinaison de touche Crtl + C.

Ouvrez l'application dans Visual Studio Code.  Pour cela, cliquez sur le menu File, puis sur Open Folder, ensuite sectionnez le répertoire dans lequel a été créée votre application.

Lorsque votre projet va s'ouvrir, Visual Studio Code va essayer de restaurer les dépendances et les fichiers nécessaires pour la génération et le débogage de votre application :

Image non disponible

Cliquez sur Yes pour ajouter à votre projet les assets pour le debug et la build.

Pour exécuter l'application dans Visual Studio Code en mode debug, tapez sur F5.

Image non disponible

Votre navigateur par défaut sera automatiquement lancé, avec votre application en cours d'exécution.

 

V. Structure d'un projet ASP.NET Core MVC

Le modèle de projet que nous avons utilisé nous a permis de créer une application ASP.NET Core MVC. Nous allons passer en revue quelques spécificités de ce projet pour comprendre certains aspects clés du Framework.

Visual Studio Code dispose d'un explorateur de fichiers à gauche permettant de visualiser l'ensemble des dossiers et fichiers du projet.

Image non disponible

Ci-dessous les dossiers et fichiers clés à maîtriser, ainsi que leur utilité :

  • Le dossier .vscode est généré par l'éditeur et dispose d'un fichier Launch.json utilisé pour le débogage et un fichier Task.json dans lequel sont référencés les taches à exécuter (build, test, déploiement, etc.). Par défaut ce fichier contient la tache de build ;
  • Controllers : c'est dans ce dossier que seront regroupés tous les contrôleurs de l'application ;
  • Le dossier Properties contient un fichier launchSettings.json, qui sera utilisé pour définir les paramètres pour vos différents environnements de travail (environnement de développement, de test, de production, etc.). Il faut noter toutefois que ce fichier est beaucoup plus utilisé par Visual Studio ;
  • Views : le dossier Views contient tous les fichiers d'interface (la vue) ;
  • wwwroot : le fichier est l'emplacement de sauvegarde du contenu statique (images, css, fichiers JavaScript, etc.) ;
  • le fichier appsettings.json est utilisé pour l'enregistrement des paramètres, notamment la chaîne de connexion;
  • le fichier bundleconfig.json est l'emplacement où seront définis les paramètres pour le regroupement et la minification des fichiers JavaScript et CSS ;
  • Dockerfile : fichier pour la prise en charge de Docker. Intégré par défaut par le générateur Yeoman ;
  • Program.cs : fichier contenant la méthode Main ;
  • project.json : ce fichier contient l'ensemble des packages de l'application ;
  • startup.cs : fichier de démarrage de l'application qui est utilisé pour enregistrer les services et injecter des modules dans le pipeline HTTP. Nous y reviendrons.

Passons à la prochaine étape de notre tutoriel. Nous allons procéder à la configurer et à l'écriture du code nécessaire pour ajouter Entity Framework dans le projet, et procéder a la génération de la base de données en utilisant l'approche Code First. Nous allons utiliser une base de données SQL Lite.

VI. Ajout d'Entity Framework au projet

Ouvrez le fichier project.json de votre application. Ajoutez les deux dépendances suivantes dans la section dependencies :

 
Sélectionnez
"Microsoft.EntityFrameworkCore.Sqlite": "1.0.0",
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final",
   "Microsoft.EntityFrameworkCore.Design": {
     "version": "1.0.0-preview2-final",
     "type": "build" 
   }

Ainsi que la dépendance suivante dans la section tools :

 
Sélectionnez
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"

Enregistrez le fichier. Visual Studio Code ne sera pas en mesure de résoudre les nouvelles dépendances ajoutées. De ce fait, il va afficher une fenêtre vous invitant à restaurer les assemblies correspondantes. Cliquez sur restore pour lancer le processus.

Image non disponible

Votre fichier project.json devrait ressembler à ceci :

 
Sélectionnez
{
 "dependencies": {
   "Microsoft.NETCore.App": {
     "version": "1.0.0",
     "type": "platform"
   },
   "Microsoft.AspNetCore.Diagnostics": "1.0.0",
   "Microsoft.AspNetCore.Mvc": "1.0.0",
   "Microsoft.AspNetCore.Razor.Tools": {
     "version": "1.0.0-preview2-final",
     "type": "build"
   },
   "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
   "Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
   "Microsoft.AspNetCore.StaticFiles": "1.0.0",
   "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
   "Microsoft.Extensions.Configuration.Json": "1.0.0",
   "Microsoft.Extensions.Configuration.CommandLine": "1.0.0",
   "Microsoft.Extensions.Logging": "1.0.0",
   "Microsoft.Extensions.Logging.Console": "1.0.0",
   "Microsoft.Extensions.Logging.Debug": "1.0.0",
   "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
   "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0",
   "Microsoft.EntityFrameworkCore.Sqlite": "1.0.0",
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final",
   "Microsoft.EntityFrameworkCore.Design": {
     "version": "1.0.0-preview2-final",
     "type": "build" 
   }
 },
 
 "tools": {
   "BundlerMinifier.Core": "2.0.238",
   "Microsoft.AspNetCore.Razor.Tools": "1.0.0-preview2-final",
   "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final",
   "Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"
 },
 
 "frameworks": {
   "netcoreapp1.0": {
     "imports": [
       "dotnet5.6",
       "portable-net45+win8"
     ]
   }
 },
 
 "buildOptions": {
   "emitEntryPoint": true,
   "preserveCompilationContext": true
 },
 
 "runtimeOptions": {
   "configProperties": {
     "System.GC.Server": true
   }
 },
 
 "publishOptions": {
   "include": [
     "wwwroot",
     "Views",
     "Areas/**/Views",
     "appsettings.json",
     "web.config"
   ]
 },
 
 "scripts": {
   "precompile": [ "dotnet bundle" ],
   "prepublish": [ "bower install" ],
   "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
 },
 
 "tooling": {
   "defaultNamespace": "SampleApp"
 }
}

Microsoft a abandonné le fichier project.json pour adopter le format .csproj. Si vous utilisez une version de .NET Core prenant en charge le format .csproj, vous devez ajouter dans le fichier [votreapplication].csproj les références suivantes :

 
Sélectionnez
 <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore.SQLite">
      <Version>1.0.1</Version>
    </PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design">
      <Version>1.0.1</Version>
      <PrivateAssets>All</PrivateAssets>
    </PackageReference>
   <PackageReference Include="Microsoft.EntityFrameworkCore.Tools.Dotnet" Version="1.0.0" />

</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" />
</ItemGroup>

Attention, le numéro de version doit être compatible à la version de .NET Core que vous utilisez.

Si vous souhaitez migrer votre application vers le format .csproj, exécutez la commande suivante dans le répertoire de votre application :

 
Sélectionnez
Dotnet migrate

Pour vérifier que la restauration a été effectuée correctement, vous pouvez ouvrir le terminal intégré a Visual Studio Code (cliquez sur le menu View, puis sur Integrated Terminal) et exécuter la commande suivante :

 
Sélectionnez
Dotnet ef --help

Ceci fait, vous allez ajouter un nouveau dossier en cliquant sur votre application dans l'explorateur de solution, puis sur l'icône de création d'un nouveau.

Image non disponible

Vous allez nommer ce dossier Models. C'est dans ce dossier que vous allez créer tous les éléments de votre modèle. Vous allez créer un nouveau fichier User.cs. Pour cela, faites simplement un clic droit sur  le dossier Models, puis cliquez sur New File et entrez le nom du fichier (User.cs). Dans ce dernier, saisissez les lignes de code suivantes :

 
Sélectionnez
using System;
using System.IO;
 
namespace SampleApp.Models
{
  public class User
  {
 
       public int Id { get; set; }
      public string FirstName { get; set; }
      public string LastName { get; set; }
       
      public string Email { get; set; }
  }
 
}  

La classe User est une classe entité, qui est une représentation de la table User de votre base de données. Les propriétés seront les colonnes de cette table. Enregistrez les modifications.

VII. Création du DbContext

Nous allons maintenant créer la classe qui va s'occuper de gérer la communication entre les classes entités et la base de données. Cette classe va hériter de la classe DbContext.

La classe DbContext expose les fonctionnalités les plus couramment utilisées pour interroger et utiliser les données d'entités en tant qu'objets.

Cette classe doit contenir une propriété DbSet fortement typée, correspondant à votre classe entité (user). Les attributs DbSet vont permettre de gérer la correspondance avec les tables de la base de données.

Créez ensuite un fichier SampleAppContext.cs, en procédant de la même façon.

Ajoutez le code suivant dans ce fichier :

 
Sélectionnez
using System;
using System.IO;
using Microsoft.EntityFrameworkCore;
 
namespace SampleApp.Models
{
 
public class SampleAppContext : DbContext
  {
      public SampleAppContext(DbContextOptions<SampleAppContext> options)
          : base(options)
      { }
      public DbSet<User> Users { get; set; }
  }
}

Enregistrez les modifications.

Vous allez utiliser l'injection des dépendances qu'offre ASP.NET Core pour enregistrer votre Context. Pour cela, ouvrez le fichier Startup.cs de votre projet. Ajoutez dans un premier temps les références suivantes :

 
Sélectionnez
using SampleApp.Models;

using Microsoft.EntityFrameworkCore;

Dans la méthode ConfigureServices, ajoutez la ligne de code suivante :

 
Sélectionnez
services.AddEntityFrameworkSqlite()
                .AddDbContext<SampleAppContext>(options => options.UseSqlite(Configuration["Data:DefaultConnection:SqliteConnectionString"]));

Le code de cette méthode est le suivant :

 
Sélectionnez
public void ConfigureServices(IServiceCollection services)
 
       {
 
           // Add framework services.
 
            services.AddEntityFrameworkSqlite()
                .AddDbContext<SampleAppContext>(options => options.UseSqlite(Configuration["Data:DefaultConnection:SqliteConnectionString"]));
 
 
           services.AddMvc();
 
       }

Configuration["Data:DefaultConnection:SqliteConnectionString"] permet de récupérer la chaîne de connexion dans le fichier de configuration Appsettings.json. Vous devez donc éditer ce fichier et ajouter les informations suivantes :

 
Sélectionnez
"Data": {
    "DefaultConnection": {
       "SqliteConnectionString": "Data Source=sampledb.db"
   }
  }

Enregistrez les modifications et compilez votre application en utilisant la commande suivante, pour vous assurer que tout est correct :

 
Sélectionnez
Dotnet build

VIII. Génération de la base de données

Passons maintenant à la génération de la base de données en utilisant Code First Migrations. Cette fonctionnalité permet d'appliquer les mises à jour du modèle à la base de données. Elle se résume essentiellement en l'exécution de deux commandes :

  • Add-Migration : génère un script de migration correspondant aux modifications qui ont été apportées au modèle ;
  • Update-Database : met à jour la base de données en appliquant les migrations en attente.

Vous allez ouvrir la console intégrée de Visual Studio Code et exécuter la commande suivante :

 
Sélectionnez
dotnet ef migrations add Initial

Cette commande va créer un dossier Migrations dans votre application avec le script permettant de créer la table User.

Exécutez la commande suivante pour appliquer ce script. Comme la base de données n'existe pas, elle sera automatiquement créée :

 
Sélectionnez
dotnet ef database update

IX. Création du contrôleur

Ceci fait, nous allons créer le contrôleur avec les méthodes d'action permettant de consulter, créer, modifier et supprimer un utilisateur. Malheureusement, avec Visual Studio Code, nous ne disposons pas du scaffolding CRUD pour générer le code de notre contrôleur avec ses méthodes d'action et les vues correspondantes.

Toutefois, pour ajouter un nouveau contrôleur à notre application, nous allons utiliser Yeoman. Ouvrez le terminal et exécutez la commande suivante :

 
Sélectionnez
Yo aspnet:MvcController UsersController
Image non disponible

Cette commande va créer dans le dossier Controllers le fichier UsersController.cs, avec le code suivant :

 
Sélectionnez
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
 
// For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
 
namespace SampleApp.Controllers
{
   public class UsersController : Controller
   {
       // GET: /<controller>/
       public IActionResult Index()
       {
           return View();
       }
   }
}

Ajoutez dans un premier temps les références suivantes dans le fichier UsersController :

 
Sélectionnez
using Microsoft.EntityFrameworkCore;
using SampleApp.Models;

Supprimez ensuite la méthode Index()

 
Sélectionnez
// GET: /<controller>/
       public IActionResult Index()
       {
           return View();
       }

Vous allez déclarer une nouvelle propriété de type SampleAppContext :

 
Sélectionnez
private readonly SampleAppContext _context;

Ensuite, vous devez ajouter un constructeur à votre contrôleur, qui prend en paramètre un objet de type de SampleAppContext, et l'affecte à cette propriété :

 
Sélectionnez
public UsersController(SampleAppContext context)
      {
          _context = context;    
      }

Le code complet de votre contrôleur devrait ressembler à ceci :

 
Sélectionnez
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Mvc;
using SampleApp.Models;
 
// For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
 
namespace SampleApp.Controllers
{
   public class UsersController : Controller
   {
        private readonly SampleAppContext _context;
      public UsersController(SampleAppContext context)
      {
          _context = context;    
      }
   }
}

X. Création des méthodes d'action et des vues

Nous allons maintenant créer les méthodes d'action et les vues permettant d'effectuer les opérations CRUD sur la table Users. Vous allez créer un nouveau dossier Users dans le dossier View. Avant de se lancer, nous allons dans un premier temps nous familiariser avec les Tag Helpers, qui nous permettront de construire nos formulaires.

X-A. Comprendre les Tag Helpers

La vue est constituée du contenu HTML, JavaScript et CSS. Le CSS sera utilisé pour la mise en page. Le framework Boostrap est celui utilisé coté IU. En plus de ces éléments qui sont interprétés cotés clients par le navigateur, nous avons du contenu provenant de notre contrôleur qui est traité et affiché dans la vue. Ces données à la base ne sont pas interprétables par le navigateur. C'est à ce stade qu'intervient un moteur de vue.

Le moteur de vue va offrir les éléments nécessaires pour insérer du code serveur dans une page Web qui peut également contenir du HTML, du CSS et des scripts JavaScript. Lorsque l'utilisateur accède à une page, le serveur exécute ce code et génère dynamiquement à la volée du code purement HTML qui est envoyé vers le client, comme c'est le cas pour les pages ASP.NET standard.

Le moteur de vue utilisé dans les projets ASP.NET MVC est Razor. Ce dernier a été introduit avec ASP.NET MVC 3. Razor a été conçu pour permettre de mixer facilement le contenu serveur avec du code HTML. Cependant, il introduit de nouveaux concepts, notamment les HTML Helpers, qui nécessitent de l'apprentissage supplémentaire pour les développeurs. Par ailleurs, l'interprétation d'une vue Razor est beaucoup plus difficile pour un développeur Frond-End ou un designer.

Pour alléger le code de la vue et rendre celui-ci moins difficile à interpréter pour un développeur ne maîtrisant que le HTML, Microsoft a introduit avec ASP.NET Core les Tag Helpers comme une alternative aux HTML Helpers.

Les Tag Helper permettent d'étendre la syntaxe du HTML et y ajouter du code serveur qui participera à la création et au rendu du contenu HTML.

X-A-1. Tag Helper Input

Concrètement, dans une balise HTML standard, vous aurez de nouveaux attributs que vous pouvez utiliser pour le rendu du contenu coté serveur.

Par exemple, l'utilisation de la balise Input, en liant ce dernier directement à une propriété de votre modèle dans une vue se fait comme suit :

 
Sélectionnez
<input asp-for="FirstName" class="form-control" />

A l'exécution de votre application, le Tag Helper Input sera interprété et le code suivant sera généré et retourné au navigateur :

 
Sélectionnez
<input class="form-control" data-val="true" data-val-required="The First name field is required." id="FirstName" name="FirstName" value="" type="text"></input>

Vous remarquez la présence de l'attribut asp-for (vous pouvez également simplement utiliser For) avec pour valeur FirstName. Au moment de l'exécution de la page, Razor va lier cette valeur avec la propriété correspondante dans le modèle :

 
Sélectionnez
[Required]
[Display(Name = "First Name")]
 public string FirstName { get; set; }

Le type de la propriété et les annotations disponibles sur cette dernière ([Required]) vont permettre de générer les attributs type, data-val et data-val-required.

X-A-2. Le tag helper Validation Message

A la suite du Input, ce tage helper va permettre d'afficher à coté de ce champ un message d'erreur de validation. Il s'utilise comme suit :

 
Sélectionnez
<span asp-validation-for="FirstName" class="text-danger" />

Ce qui va générer le code HTML suivant :

 
Sélectionnez
<span class="field-validation-valid"
  data-valmsg-for="FirstName"
  data-valmsg-replace="true"></span>

data-valmsg va permettre de créer la liaison avec la propriété du modèle (FirstName) à valider et afficher le message d'erreur indiqué. Lorsqu'une erreur de validation sera levée (champ obligatoire) côté client, jQuery va afficher le message d'erreur dans la balise <span>.

 
Sélectionnez
<span asp-validation-for="LastName" class="text-danger" />

X-A-3. Le tag textarea

Similaire au tag helper Input, il sera utilisé pour générer la balise textarea.

Par exemple, si vous disposez de la propriété suivant dans votre modèle :

 
Sélectionnez
[MinLength(5)]
[MaxLength(1024)]
public string Description { get; set; }

L'utilisation du code ci-après dans votre vue :

 
Sélectionnez
<textarea asp-for="Description"></textarea>

Va générer le code HTML ci-dessous lorsque cette dernière sera appelée :

 
Sélectionnez
<textarea data-val="true"
   data-val-maxlength="The field Description must be a string or array type with a maximum length of &#x27;1024&#x27;."
   data-val-maxlength-max="1024"
   data-val-minlength="The field Description must be a string or array type with a minimum length of &#x27;5&#x27;."
   data-val-minlength-min="5"
   id="Description" name="Description">
  </textarea>

X-A-4. Le tag helper Label

Nous souhaitons formater le nom de notre modèle avant de l'afficher dans une vue. C'est pourquoi, dans notre modèle nous avons ajouté l'annotation [Display(Name = "First Name")].

Le tag helper Label va nous permettre d'aller chercher ce nom et l'afficher dans notre page.

En l'utilisant comme suit dans une vue Razor :

 
Sélectionnez
<label asp-for="FirstName" class="col-md-2 control-label"></label>

Nous obtenons le code suivant à l'exécution dans le navigateur :

 
Sélectionnez
<label asp-for="FirstName" class="col-md-2 control-label"></label>

X-A-5. Le Tag Helper Form

Il s'agit de la balise HTML Form avec des nouvelles attributs qu'apportent Razor coté serveur qui vont permettre lors de l'envoi du formulaire de sélectionner le contrôleur et l'action adéquats.

Il s'utilise comme suit :

 
Sélectionnez
<form asp-controller="User" asp-action="Create" method="post">
    
</form>

Vous remarquez la présence des nouvelles attributs asp-controller et asp-action qui vont permettre de définir le contrôleur et l'action qui seront appelés lors de l'envoi du formulaire.

Le code HTML qui est généré à l'exécution est le suivant :

 
Sélectionnez
<form method="post" action="/User/Create">
     <input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>" />
    </form>

Le Tag Helper Form génère l'input Request Verification Token pour la protection contre les attaques permettant l'injection de contenu.

X-A-6. Le Tag Helper Anchor

Le Tag Helper Anchor est utilisé pour la génération des liens hypertexte dans une vue. Ses attributs les plus importants sont asp-controller qui va permettre de faire une liaison avec le contrôleur et asp-action pour l'action du contrôleur qui sera appelée.

Par exemple, la ligne de code suivante dans une vue Razor :

 
Sélectionnez
<a asp-controller="User" asp-action="Create">New User</a>

Va générer le code HTML suivant :

 
Sélectionnez
<a href="/User/Create">New User</a>

Vous pouvez ignorer le paramètre asp-controlleur si la vue cible est dans le même répertoire que la vue initiale.

Pour ajouter un paramètre au lien, vous devez insérer l'attribut asp-route-id :

 
Sélectionnez
<a asp-controller="User" asp-action="Edit" asp-route-id="2">Edit</a>

Ce code va produire la sortie HTML suivante :

 
Sélectionnez
<a href="/User/Edit/2">Edit</a>

X-B. Création de la méthode d'action et la vue Index

Ouvrez le fichier UsersController et ajoutez la méthode d'action suivante à ce dernier :

 
Sélectionnez
// GET: Users
      public async Task<IActionResult> Index()
      {
          return View(await _context.Users.ToListAsync());
      }

Cette méthode d'action permet de retourner la liste des utilisateurs de la base de données.

Nous allons créer la vue Index.cshtml permettant d'afficher cette liste. Pour le faire, ouvrez le terminal intégré à Visual Studio Code et exécutez la commande suivante :

 
Sélectionnez
yo aspnet:MvcView Users/Index

Ouvrez ce fichier et remplacez son contenu par le code suivant :

 
Sélectionnez
@model IEnumerable<SampleApp.Models.User>

@{
 
   ViewData["Title"] = "Index";
 
}

<h2>Index</h2>

<p>
 
   <a asp-action="Create">Create New</a>
 
</p>
 
<table class="table">
 
   <thead>
 
       <tr>
 
           
 
           <th>
 
               @Html.DisplayNameFor(model => model.FirstName)
 
           </th>
 
           <th>
 
               @Html.DisplayNameFor(model => model.LastName)
 
           </th>
 
           <th>
 
               @Html.DisplayNameFor(model => model.Email)
 
           </th>
 
           <th></th>
 
       </tr>
 
   </thead>
 
   <tbody>
 
@foreach (var item in Model) {
 
       <tr>
 
           <td>
 
               @Html.DisplayFor(modelItem => item.FirstName)
 
           </td>
 
           <td>
 
               @Html.DisplayFor(modelItem => item.LastName)
 
           </td>
 
           <td>
 
               @Html.DisplayFor(modelItem => item.Email)
 
           </td>
 
           <td>
 
               <a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
 
               <a asp-action="Details" asp-route-id="@item.Id">Details</a> |
 
               <a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
 
           </td>
 
       </tr>
 
}
 
   </tbody>
 
</table>

Exécutez l'application en utilisant la touche F5 du clavier. Dans le navigateur ajoutez /users à la suite du lien dans la barre d'adresse. Vous aurez le résultat suivant :

Image non disponible

FirstName et LastName ont besoin de formatage. Dans le formulaire nous devons en principe avoir First Name et Last Name. Pour ne pas avoir à faire cette modification dans la vue, et de ce fait dans toutes les vues ou ces champs sont utilisés, nous allons ajouter allons utiliser l'attribut [Display] des DataAnnotations dans la classe User :

 
Sélectionnez
[Display(Name = "First Name")]
      public string FirstName { get; set; }
     
      [Display(Name = "Last Name")]
      public string LastName { get; set; }

Enregistrez les modifications et exécutez à nouveau votre application. Vous aurez le résultat suivant :

Image non disponible

X-C. Création des méthodes d'action et la vue Create

Pour l'insertion, il y aura deux méthodes d'action. La première sera appelée suite à une requête Get et permettra d'afficher le formulaire d'insertion. La seconde sera appelée suite à une requête Post, et permettra d'enregistrer les informations contenues dans le formulaire. Le code pour ces deux méthodes d'action est le suivant :

 
Sélectionnez
  // GET: Users/Create
      public IActionResult Create()
      {
          return View();
      }
      // POST: Users/Create
      [HttpPost]
      [ValidateAntiForgeryToken]
      public async Task<IActionResult> Create([Bind("Id,Email,FirstName,LastName")] User User)
      {
          if (ModelState.IsValid)
          {
              _context.Add(User);
              await _context.SaveChangesAsync();
              return RedirectToAction("Index");
          }
          return View(User);
      }

Pour créer la vue Create.cshtml, exécutez la commande suivante dans le terminal :

 
Sélectionnez
yo aspnet:MvcView Users/Create

Remplacez son contenu par le code suivant :

 
Sélectionnez
@model SampleApp.Models.User
 
@{
 
   ViewData["Title"] = "Create";
 
}
 
<h2>Create</h2>
 
<form asp-action="Create">
 
   <div class="form-horizontal">
 
       <h4>User</h4>
 
       <hr />
 
       <div asp-validation-summary="ModelOnly" class="text-danger"></div>
 
      
 
       <div class="form-group">
 
           <label asp-for="FirstName" class="col-md-2 control-label"></label>
 
           <div class="col-md-10">
 
               <input asp-for="FirstName" class="form-control" />
 
               <span asp-validation-for="FirstName" class="text-danger" />
 
           </div>
 
       </div>
 
       <div class="form-group">
 
           <label asp-for="LastName" class="col-md-2 control-label"></label>
 
           <div class="col-md-10">
 
               <input asp-for="LastName" class="form-control" />
 
               <span asp-validation-for="LastName" class="text-danger" />
 
           </div>
 
       </div>
 
       <div class="form-group">
 
           <label asp-for="Email" class="col-md-2 control-label"></label>
 
           <div class="col-md-10">
 
               <input asp-for="Email" class="form-control" />
 
               <span asp-validation-for="Email" class="text-danger" />
 
           </div>
 
       </div>
 
       <div class="form-group">
 
           <div class="col-md-offset-2 col-md-10">
 
               <input type="submit" value="Create" class="btn btn-default" />
 
           </div>
 
       </div>
 
   </div>
 
</form>
 
<div>
 
   <a asp-action="Index">Back to List</a>
 
</div>
 
@section Scripts {
 
   @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
 
}

Ceci fait, lancez le débogage de l'application (F5), saisissez le lien pour accéder à la page Users et cliquez sur Create New. Ops. On obtient une exception :

Image non disponible

Cette exception est due au fait que vous appelez une vue partielle dans la vue Create.cshtml, qui n'existe pas.

 
Sélectionnez
@section Scripts {
 
   @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
 
}

Ce fichier doit permettre de charger les scripts (css et js) qui seront utilisés pour valider les informations du formulaire. Par exemple, le nom et le prénom qui doivent être obligatoires, ou encore le format de l'adresse mail.

Vous devez donc créer le fichier _ValidationScriptsPartial.cshtml dans le dossier View/Shared en utilisant la commande suivante :

 
Sélectionnez
Yo aspnet:MvcView Shared/_ValidationScriptsPartial

Ouvrez ce fichier et remplacez son contenu par le suivant :

 
Sélectionnez
 
<environment names="Development">
 
   <script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
 
   <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
 
</environment>
 
<environment names="Staging,Production">
 
   <script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.14.0/jquery.validate.min.js"
 
           asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js"
 
           asp-fallback-test="window.jQuery && window.jQuery.validator">
 
   </script>
 
   <script src="https://ajax.aspnetcdn.com/ajax/jquery.validation.unobtrusive/3.2.6/jquery.validate.unobtrusive.min.js"
 
           asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
 
           asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive">
 
   </script>
 
</environment>

Ceci fait, vous allez encore modifier le fichier User.cs et ajouter les attributs [Require] et [DataType(DataType.EmailAddress)] pour la validation :

 
Sélectionnez

      [Required]
      [Display(Name = "First Name")]
      public string FirstName { get; set; }
     
      [Required]
      [Display(Name = "Last Name")]
      public string LastName { get; set; }
       
       [Required]
       [DataType(DataType.EmailAddress)]
      public string Email { get; set; }

Ceci fait, exécutez de nouveau votre application et affichez la page Create (http://localhost:5000/users/Create). Si vous cliquez sur le bouton Create sans remplir les champs, vous aurez les erreurs suivantes :

Image non disponible

Si vous remplissez correctement les champs, les informations seront enregistrées et vous serez redirigé vers la page d'accueil avec la liste des utilisateurs :

Image non disponible

Vous remarquez la présence des liens Edit, Details et Delete. Nous devons écrire les méthodes pour ces derniers.

X-D. Création des méthodes d'action et la vue pour Edit

Nous aurons également deux méthodes d'action pour Edit. La première (Get) qui affiche le formulaire d'édition prérempli avec les informations sur l'utilisateur à modifier, et la seconde (Post) qui permettra d'enregistrer les modifications. Voici le code pour ces deux méthodes d'action :

 
Sélectionnez
// GET: Users/Edit/5
      public async Task<IActionResult> Edit(int? id)
      {
          if (id == null)
          {
              return NotFound();
          }
          var User = await _context.Users.SingleOrDefaultAsync(m => m.Id == id);
          if (User == null)
          {
              return NotFound();
          }
          return View(User);
      }

      // POST: Users/Edit/5
       [HttpPost]
      [ValidateAntiForgeryToken]
      public async Task<IActionResult> Edit(int id, [Bind("Id,Email,FirstName,LastName")] User User)
      {
          if (id != User.Id)
          {
              return NotFound();
          }
          if (ModelState.IsValid)
          {
              try
              {
                  _context.Update(User);
                  await _context.SaveChangesAsync();
              }
              catch (DbUpdateConcurrencyException)
              {
                  if (!UserExists(User.Id))
                  {
                      return NotFound();
                  }
                  else
                  {
                      throw;
                  }
              }
              return RedirectToAction("Index");
          }
          return View(User);
      }

 private bool UserExists(int id)
      {
          return _context.Users.Any(e => e.Id == id);
      }

Utilisez le terminal pour créer le fichier Edit.cshtml (yo aspnet:MvcView Users/Edit) et remplacez son contenu par :

 
Sélectionnez
@model SampleApp.Models.User
 
@{
 
   ViewData["Title"] = "Edit";
 
}

<h2>Edit</h2>

<form asp-action="Edit">
 
   <div class="form-horizontal">
 
       <h4>User</h4>
 
       <hr />
 
       <div asp-validation-summary="ModelOnly" class="text-danger"></div>
 
   <input type="hidden" asp-for="Id" />
 
      
 
       <div class="form-group">
 
           <label asp-for="FirstName" class="col-md-2 control-label"></label>
 
           <div class="col-md-10">
 
               <input asp-for="FirstName" class="form-control" />
 
               <span asp-validation-for="FirstName" class="text-danger" />
 
           </div>
 
       </div>
 
       
 
       <div class="form-group">
 
           <label asp-for="LastName" class="col-md-2 control-label"></label>
 
           <div class="col-md-10">
 
               <input asp-for="LastName" class="form-control" />
 
               <span asp-validation-for="LastName" class="text-danger" />
 
           </div>
 
       </div>

        <div class="form-group">
 
           <label asp-for="Email" class="col-md-2 control-label"></label>
 
           <div class="col-md-10">
 
               <input asp-for="Email" class="form-control" />
 
               <span asp-validation-for="Email" class="text-danger" />
 
           </div>
 
       </div>
 
       <div class="form-group">
 
           <div class="col-md-offset-2 col-md-10">
 
               <input type="submit" value="Save" class="btn btn-default" />
 
           </div>
 
       </div>
 
   </div>
 
</form>

<div>
 
   <a asp-action="Index">Back to List</a>
 
</div>

@section Scripts {
 
   @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
 
}

En exécutant l'application et en cliquant sur Edit dans la liste des utilisateurs, vous obtiendrez le résultat suivant :

Image non disponible

X-E. Création de la méthode d'action et la vue Detail

La méthode d'action Detail prend en paramètre l'ID de l'utilisateur et retourne les informations concernant ce dernier. Son code est le suivant :

 
Sélectionnez
// GET: Users/Details/5
      public async Task<IActionResult> Details(int? id)
      {
          if (id == null)
          {
              return NotFound();
          }
          var User = await _context.Users.SingleOrDefaultAsync(m => m.Id == id);
          if (User == null)
          {
              return NotFound();
          }
          return View(User);
      }

Ajoutez ce code au contrôleur Users et enregistrez les modifications.

Créez ensuite la vue Details.cshtml (yo aspnet:MvcView Details) et remplacez son contenu par le suivant :

 
Sélectionnez
@model SampleApp.Models.User

@{
 
   ViewData["Title"] = "Details";
 
}

<h2>Details</h2>

<div>
 
   <h4>User</h4>
 
   <hr />
 
   <dl class="dl-horizontal">
 
       
 
       <dt>
 
           @Html.DisplayNameFor(model => model.FirstName)
 
       </dt>
 
       <dd>
 
           @Html.DisplayFor(model => model.FirstName)
 
       </dd>
 
       <dt>
 
           @Html.DisplayNameFor(model => model.LastName)
 
       </dt>
 
       <dd>
 
           @Html.DisplayFor(model => model.LastName)
 
       </dd>
 
       <dt>
 
           @Html.DisplayNameFor(model => model.Email)
 
       </dt>
 
       <dd>
 
           @Html.DisplayFor(model => model.Email)
 
       </dd>
 
   </dl>
 
</div>
 
<div>
 
   <a asp-action="Edit" asp-route-id="@Model.Id">Edit</a> |
 
   <a asp-action="Index">Back to List</a>
 
</div>

Enregistrez les modifications et lancez le débogage de l'application (F5). Dans la liste des utilisateurs, cliquez sur Details. Vous obtiendrez le résultat suivant :

Image non disponible

X-F. Création des méthodes d'action et la vue Delete

Pour la suppression, nous aurons également deux méthodes d'action. L'une pour retourner suite à une requête Get les informations à supprimer, et l'autre qui effectuera la suppression lorsque l'utilisateur cliquera sur le bouton delete. Le code, à ajouter le fichier UsersController.cs, pour ces méthodes d'action est le suivant :

 
Sélectionnez
// GET: Users/Delete/5
      public async Task<IActionResult> Delete(int? id)
      {
          if (id == null)
          {
              return NotFound();
          }
          var User = await _context.Users.SingleOrDefaultAsync(m => m.Id == id);
          if (User == null)
          {
              return NotFound();
          }
          return View(User);
      }
      // POST: Users/Delete/5
      [HttpPost, ActionName("Delete")]
      [ValidateAntiForgeryToken]
      public async Task<IActionResult> DeleteConfirmed(int id)
      {
          var User = await _context.Users.SingleOrDefaultAsync(m => m.Id == id);
          _context.Users.Remove(User);
          await _context.SaveChangesAsync();
          return RedirectToAction("Index");
      }

Créez ensuite la vue Delete.cshtml (yo aspnet:MvcView Delete) et remplacez son contenu par le suivant :

 
Sélectionnez
@model SampleApp.Models.User

@{
 
   ViewData["Title"] = "Delete";
 
}

<h2>Delete</h2>

<h3>Are you sure you want to delete this?</h3>
 
<div>
 
   <h4>User</h4>
 
   <hr />
 
   <dl class="dl-horizontal">
 
       
 
       <dt>
 
           @Html.DisplayNameFor(model => model.FirstName)
 
       </dt>
 
       <dd>
 
           @Html.DisplayFor(model => model.FirstName)
 
       </dd>
 
       <dt>
 
           @Html.DisplayNameFor(model => model.LastName)
 
       </dt>
 
       <dd>
 
           @Html.DisplayFor(model => model.LastName)
 
       </dd>
 
       <dt>
 
           @Html.DisplayNameFor(model => model.Email)
 
       </dt>
 
       <dd>
 
           @Html.DisplayFor(model => model.Email)
 
       </dd>
 
   </dl>
 
   
 
   <form asp-action="Delete">
 
       <div class="form-actions no-color">
 
           <input type="submit" value="Delete" class="btn btn-default" /> |
 
           <a asp-action="Index">Back to List</a>
 
       </div>
 
   </form>
 
</div>

À l'exécution et suite à un clic sur Delete dans la liste des utilisateurs, vous aurez le résultat suivant :

Image non disponible

Pour finir, vous allez modifier le fichier _Layout.cshtml (Views/Shared) et ajoutez la ligne de code suivante :

 
Sélectionnez
<li><a asp-area="" asp-controller="Users" asp-action="Index">Users</a></li>

Juste après la ligne de code :

 
Sélectionnez
<li><a asp-area="" asp-controller="Home" asp-action="Contact">Contact</a></li>

Ce qui produit le résultat suivant à l'exécution :

Image non disponible

XI. Déploiement en utilisant Nginx comme reverse proxy

Kestrel offre de bonnes performances pour le rendu du contenu dynamique. Mais, c'est un serveur démuni de nombreuses fonctionnalités. Il est essentiellement dédié au développement.

Dans un environnement de production, il doit être couplé avec d'autres serveurs, dont IIS, ou Nginx, qui apporteront des fonctionnalités additionnelles. Dans notre cas, nous allons configurer Nginx pour utiliser ce dernier comme reverse proxy, afin d'offrir des fonctionnalités supplémentaires comme le rendu du contenu statique, la mise en cache ou encore la compression des requêtes.

XI-A. Installation de Nginx

Nous allons commencer par installer le serveur Nginx. Ouvrez le terminal et exécutez la commande suivante :

 
Sélectionnez
sudo apt-get install nginx

Cela fait, vous allez démarrer Nginx en exécutant la commande suivante :

 
Sélectionnez
sudo service nginx start

XI-B. Configuration de Nginx

Vous devez maintenant configurer Nginx pour qu'il agisse comme reverse proxy pour Kestrel. Nous voulons qu'à chaque requête sur le port 80, Nginx redirige le trafic vers le port 5050 qui sera celui utilisé par notre application.

Pour y parvenir, nous devons éditer le fichier /etc/nginx/sites-available/default . Ouvrez ce dernier en utilisant la commande :

 
Sélectionnez
sudo -i gedit /etc/nginx/sites-available/default

Changez son contenu par le suivant et enregistrez :

 
Sélectionnez
server {
   listen 80;
   location / {
       proxy_pass http://localhost:5050;
       proxy_http_version 1.1;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection keep-alive;
       proxy_set_header Host $host;
       proxy_cache_bypass $http_upgrade;
   }
}

Exécutez les deux commandes suivantes pour vous rassurer que le fichier de config est correct et procéder au chargement de ce dernier :

 
Sélectionnez
sudo nginx -t
sudo nginx -s reload

Les projets ASP.NET Core sont configurés pour utiliser par défaut le port 5000. Comme nous souhaitons utiliser le port 5050 pour notre application, nous allons donc apporter quelques modifications à notre application pour prendre cela en compte.

Vous allez dans un premier temps ajouter un nouveau fichier hosting.json à votre projet, avec le contenu suivant :

 
Sélectionnez
{
 "server.urls": "http://localhost:5050"
}

Éditez ensuite le fichier Program.cs pour prendre en compte le fichier hosting.json. Vous devez l'ajouter au ConfigurationBuilder.

 
 
Sélectionnez
var config = new ConfigurationBuilder()
           .SetBasePath(Directory.GetCurrentDirectory())
           .AddJsonFile("hosting.json", optional: true)
               .AddCommandLine(args)
               .AddEnvironmentVariables(prefix: "ASPNETCORE_")
               .Build();

Vous devez intégrer le fichier hosting.json dans le package de déploiement de votre application. Pour cela, vous devez éditer le fichier project.json et ajouter hosting.json dans publishOptions :

 
Sélectionnez
"publishOptions": {
   "include": [
     "wwwroot",
     "Views",
     "Areas/**/Views",
     "appsettings.json",
     "web.config",
     "hosting.json"
   ]
 },

Compilez à nouveau votre application et procédez à son exécution :

 
Sélectionnez
Dotnet build
Dotnet run

Ouvrez votre navigateur et saisissez http://localhost/  pour lancer votre application.

XI-C. Publication de l'application et configuration du superviseur

À ce stade, pour accéder à l'application depuis le navigateur, vous devez au préalable exécuter la commande dotnet run. De plus, nous n'avons pas publié l'application dans son répertoire de destination.

Pour la suite, nous allons publier notre application et configurer l'outil superviseur. Il s'agit d'un système de contrôle de processus qui va permettre de lancer l'application et maintenir cette dernière en exécution.

Pour commencer, vous allez publier l'application :

 
Sélectionnez
dotnet publish

Après l'exécution de cette commande, vous obtenez le répertoire dans lequel l'application a été publiée :

 
Sélectionnez
publish: Published to /home/hinault/projects/SampleApp/bin/Debug/netcoreapp1.0/publish

Vous devez ensuite copier cette dernière dans son répertoire de destination (/var/www/sampleapp) :

 
Sélectionnez
sudo cp -a /home/hinault/projects/SampleApp/bin/Debug/netcoreapp1.0/publish /var/www/sampleapp

Cela fait, vous devez installer supervisor en utilisant la commande suivante :

 
Sélectionnez
sudo apt-get install supervisor

Ensuite, vous devez créer un nouveau fichier de configuration (sampleapp.conf) dans le dossier etc/supervisor/conf.d/ avec le contenu suivant, pour permettre à supervisor de lancer votre application :

 
Sélectionnez
[program:sampleapp]
command=/usr/bin/dotnet /var/www/sampleapp/SampleApp.dll
directory=/var/www/sampleapp/
autostart=true
autorestart=true
stderr_logfile=/var/log/sampleapp.err.log
stdout_logfile=/var/log/sampleapp.out.log
environment=HOME=/var/www/,ASPNETCORE_ENVIRONMENT=Production
user=www-data
stopsignal=INT
stopasgroup=true
killasgroup=true

Pour finir, vous devez exécuter les deux commandes suivantes pour arrêter et relancer supervisor :

 
Sélectionnez
sudo service supervisor stop
sudo service supervisor start

XII. Déploiement avec un conteneur Docker

Dans cette section, nous verrons comment utiliser un conteneur Docker pour déployer notre application. Docker est une application open source permettant d'automatiser  le déploiement d'applications dans des conteneurs logiciel.

La première chose à faire sera d'installer Docker en utilisant les commandes suivantes :

 
Sélectionnez
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9
sudo apt-get update
sudo apt-get install lxc-docker

Pour s'assurer que Docker est installé, exécutez la commande suivante :

 
Sélectionnez
Docker

Ou

 
Sélectionnez
docker run hello-world
Image non disponible

La création d'une application ASP.NET Core avec le générateur Yeoman ajoute par défaut à cette dernière un fichier Dockerfile. Le fichier est disponible à la racine du projet et contient les configurations nécessaires pour exécuter votre application dans un conteneur docker :

 
Sélectionnez
FROM microsoft/dotnet:latest
 
COPY . /app
 
WORKDIR /app
 
RUN ["dotnet", "restore"]
 
RUN ["dotnet", "build"]
 
EXPOSE 5100/tcp
 
ENTRYPOINT ["dotnet", "run", "--server.urls", "http://0.0.0.0:5100"]
 

Lorsque nous allons procéder à la build de ce fichier avec Docker, une nouvelle image Docker sera créée. Cette dernière sera basée sur l'image Microsoft/dotnet. Cette image contient la dernière version du SDK .NET Core (le framework .NET Core et les outils en ligne de commande), permettant d'exécuter une application ASP.NET Core.  Les fichiers du projet seront ensuite copiés dans un conteneur et ce dernier sera généré par Docker. Les commandes dotnet restore et dotnet build seront exécutés pour restaurer les packages du projet et générer ce dernier.

Puisqu'il s'agit d'une application web, le port sur lequel cette dernière doit être visible doit être défini, ainsi que son URL.

Vous devez exécuter la commande suivante dans le répertoire de votre application pour lancer la build de ce fichier, en spécifiant le nom de votre application après l'argument -t :

 
Sélectionnez
sudo docker build -t sampleapp
Image non disponible

Cette commande doit s'achever avec le « . »

XII-A. Exécution de l'application

Vous pouvez vérifier que votre image a été créée correctement en utilisant les commandes suivantes :

 
Sélectionnez
sudo docker images
Image non disponible

Pour lancer votre application, exécutez simplement la fenêtre suivante :

 
Sélectionnez
sudo docker run -it -p 5100:5100 sampleapp
Image non disponible

Une fois votre application en cours d'exécution, vous pouvez ouvrir votre navigateur et saisir son adresse (http://localhost:5100/) pour obtenir un aperçu de cette dernière.

Image non disponible

XIII. Conclusion


ASP.NET Core et les outils .NET Core sont assez robuste pour permettre la création et le déploiement d'applications Web sur Linux. Dans cet article, nous avons vu à travers un exemple concret comment procéder.

XIV. Remerciements

XV. Référence

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 2017 Hinault Romaric. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts. Droits de diffusion permanents accordés à Developpez LLC.