Apprendre à créer une application CRUD avec ASP.NET Core Razor Pages sous Visual Studio Code et Entity Framework Core,
Un tutoriel d'Hinault Romaric

Le , par Hinault Romaric, Responsable .NET
Pour les développeurs qui veulent mettre en place de petites applications Web sans avoir à faire face aux contraintes architecturales qu'impose MVC, Razor Pages est désormais offert avec ASP.NET Core 2.0.

ASP.NET Core Razor Pages apporte un modèle de programmation différent de ASP.NET MVC. Dans ce billet de blog, nous verrons comment mettre en place les opérations CRUD pour une application Razor Pages. Nous allons mettre en place le code nécessaire pour générer la base de données, enregistrer des données, afficher, modifier et supprimer.

Création de l'application

ASP.NET Core 2.0 offre de nombreux modèles de projet permettant de créer des applications Web MVC, Razor Pages, Web API et SPA (Single Page Application). Les modèles sont intégrés directement au SDK de l’outil. La création d’un nouveau projet se fait en invite de commande en utilisant la commande dotnet new, suivi du nom du modèle de projet.

Pour créer le projet de démarrage en utilisant le modèle offert par défaut, vous allez lancer VS Code et ouvrir le terminal intégré en cliquant sur le menu Afficher, puis sur Terminal Intégré.

Positionnez-vous sur le dossier dans le lequel vous souhaitez créer votre application, puis exécutez la commande :

Code : Sélectionner tout
1
2
 
Dotnet new razor -n « nomduprojet »
Création du modèle

Vous allez créer un nouveau dossier Models, et y ajouter un fichier Student.cs. avec le contenu suivant :

Code c# : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using System; 
using System.ComponentModel.DataAnnotations; 
  
namespace RazorDemo.Models 
{ 
  
     public class Student 
   { 
       public int Id { get; set; } 
  
       [Required] 
       [Display(Name="First Name")] 
       [StringLength(50)] 
       public string FirstName { get; set; } 
  
       [Required] 
       [Display(Name="Last Name")] 
       [StringLength(50)] 
       public string LastName { get; set; } 
  
       [Required] 
       [DataType(DataType.EmailAddress)] 
       public string Email { get; set; } 
   } 
  
}

Création du DBContext

Vous venez de définir une table de votre base de données. Maintenant, vous allez créer le DbContext. Pour cela, vous devez ajouter un nouveau fichier RazorDemoContext.cs au dossier Models de votre projet. Dans ce dernier, ajoutez le code suivant :

Code c# : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using System; 
using Microsoft.EntityFrameworkCore; 
  
namespace RazorDemo.Models 
{ 
public class RazorDemoContext : DbContext 
{ 
    public RazorDemoContext(DbContextOptions<RazorDemoContext> options) 
            : base(options) 
    { 
    } 
  
    public DbSet<Student> Student { get; set; } 
} 
}

La classe RazorDemoContext est un élément clé dans l’utilisation d’Entity Framework. Ce dernier sert de pont entre vos entités et votre base de données. Le DbContext va être utilisé pour toutes les interactions avec la base de données (sélection des données, enregistrement, mise à jour, suppression, etc.)

Enregistrement du DBContext

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

Code c# : Sélectionner tout
1
2
using RazorDemo.Models; 
using Microsoft.EntityFrameworkCore;

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

Code c# : Sélectionner tout
1
2
services.AddDbContext<RazorDemoContext>(options => 
        options.UseSqlite(Configuration.GetConnectionString("SqliteConnectionString")));

Le code complet de cette méthode est le suivant :

Code c# : Sélectionner tout
1
2
3
4
5
6
7
8
public void ConfigureServices(IServiceCollection services) 
      { 
  
            services.AddDbContext<RazorDemoContext>(options => 
                    options.UseSqlite(Configuration.GetConnectionString("SqliteConnectionString"))); 
  
            services.AddMvc(); 
       }

La méthode Configuration.GetConnectionString("SqliteConnectionString") va permettre d’obtenir la chaîne de connexion dans le fichier de configuration appsettings.json. Vous devez donc éditer ce fichier et y ajouter la chaîne de connexion à votre base de données :

"ConnectionStrings": {
"SqliteConnectionString": "Data Source=RazorDemo.db"
}

Le code complet de ce fichier devrait ressembler à ceci :

Code c# : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
 "Logging": { 
    "IncludeScopes": false, 
    "LogLevel": { 
      "Default": "Warning" 
    } 
  }, 
    "ConnectionStrings": { 
       "SqliteConnectionString": "Data Source=RazorDemo.db" 
  } 
}

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

Code : Sélectionner tout
Dotnet build
Génération de la base de données

Entity Framework Core offre de nombreux outils pouvant être utilisés en ligne de commande pour notamment générer une base de données, mettre à jour cette dernière en appliquant les modifications qui ont été apportées au modèle de données, etc.

Mais, avant de pouvoir les utiliser, vous devez dans un premier temps ajouter une référence au package Microsoft.EntityFrameworkCore.Tools.DotNet. Pour installer ce package, vous allez éditer le fichier .csproj et ajouter une balise DotNetCliToolReference pour Microsoft.EntityFrameworkCore.Tools.Dotnet, dans la section ItemGroup.

Code xml : Sélectionner tout
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" />

Le code complet de votre fichier .csproj devrait ressembler à ceci :

Code xml : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
<Project Sdk="Microsoft.NET.Sdk.Web"> 
  <PropertyGroup> 
    <TargetFramework>netcoreapp2.0</TargetFramework> 
  </PropertyGroup> 
  <ItemGroup> 
    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" /> 
  </ItemGroup> 
  <ItemGroup> 
    <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" /> 
  </ItemGroup> 
</Project>

Pour générer la base de données, exécutez successivement les deux commandes suivantes :

Code : Sélectionner tout
1
2
dotnet ef migrations add Initial 
Dotnet ef database update
La première commande va permettre de générer le code permettant de créer la base de données avec la table Student. La seconde commande va exécuter ce code et procéder à la création de la base de données.

Vous allez donc remarquer la présence du dossier Migrations avec des fichiers de code c# et la base de données RazorDemo.db dans le dossier racine de votre application :


Configuration du Scaffold

Maintenant que nous disposons du nécessaire pour manipuler notre base de données à partir de notre application, nous devons écrire le code permettant d’afficher, créer, modifier et supprimer des étudiants à partir des pages Web.
L’un des principes connus en programmation est le DRY (Dont Repeat Yourselft). Ce dernier encourage l’exploitation des outils existants pour mettre en place son application, afin d’éviter de mettre de gros efforts dans de nouveau développement. De ce fait, nous allons utiliser les outils existants pour générer le code permettant d’effectuer des opérations CRUD sur la table Student. Par la suite, nous verrons comment modifier le code généré pour l’adapter à nos besoins.

La première chose à faire sera l’ajout des packages nécessaires pour la prise en charge de la génération du code en invite de commande. Vous devez donc éditer le fichier .csproj et ajouter le package Microsoft.VisualStudio.Web.CodeGeneration.Tools.

Code xml : Sélectionner tout
1
2
3
4
<ItemGroup> 
    <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" /> 
    <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" /> 
  </ItemGroup>


Ensuite, vous allez exécuter successivement les commandes suivantes :

Code : Sélectionner tout
1
2
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design 
dotnet restore
Scaffold du model Student

Nous allons utiliser la commande dotnet aspnet-codegenerator razorpage, pour générer le code des pages Razor. Nous devons renseigner les options suivantes :

  • m pour le modèle : Student ;
  • dc pour le DataContext : RazorDemoContext ;
  • outDir pour le dossier de destination : Pages/Student ;
  • udl (use default layout) pour utiliser le Layout par defaut ;
  • scripts permet de spécifier que l’on souhaite que les scripts soient référencés dans les pages qui seront générées. Ces scripts serviront surtout à la validation des données des champs des formulaires.


La commande complète que vous devez exécuter est la suivante :

Code : Sélectionner tout
dotnet aspnet-codegenerator razorpage -m Student -dc RazorDemoContext -udl -outDir Pages\Students - scripts

Test de l’application

Appuyez sur F5 pour lancer le débogage de votre application. Saisissez dans votre navigateur le lien suivant http://localhost:5000/Students/Create. La page de création d’un nouvel étudiant va s’afficher :


Description des pages générées

La page Index
Examinons les fichiers Index.cshtml et Index.cshtml.cs du dossier Pages/Students. Ouvrez le fichier Index.cshtml.cs. Ce dernier contient le code suivant :

Code c# : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class IndexModel : PageModel 
    { 
        private readonly RazorDemo.Models.RazorDemoContext _context; 
  
        public IndexModel(RazorDemo.Models.RazorDemoContext context) 
        { 
            _context = context; 
        } 
  
        public IList<Student> Student { get;set; } 
  
        public async Task OnGetAsync() 
        { 
            Student = await _context.Student.ToListAsync(); 
        } 
    }

La page Index permet d’afficher la liste des étudiants. Le code métier contient la logique permettant d’afficher la liste des étudiants.
Son constructeur doit prendre en paramètre le DbContext, qui sera initialisé via l’injection de dépendances :

Code c# : Sélectionner tout
1
2
3
4
public IndexModel(RazorDemo.Models.RazorDemoContext context) 
        { 
            _context = context; 
        }

Tout le code métier qui a été généré suit ce Patern.

La méthode OnGetAsync() qui sera exécutée au chargement de la page va permettre de retourner la liste des étudiants. Le traitement de cette liste est effectué dans le fichier Index.cshtml, dont le code est le suivant :

Code c# : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@page 
@model RazorDemo.Pages.Students.IndexModel 
  
@{ 
    ViewData["Title"] = "Index"; 
} 
  
<h2>Index</h2> 
  
<p> 
    <a asp-page="Create">Create New</a> 
</p> 
<table class="table"> 
    <thead> 
        <tr> 
                <th> 
                    @Html.DisplayNameFor(model => model.Student[0].FirstName) 
                </th> 
                <th> 
                    @Html.DisplayNameFor(model => model.Student[0].LastName) 
                </th> 
                <th> 
                    @Html.DisplayNameFor(model => model.Student[0].Email) 
                </th> 
            <th></th> 
        </tr> 
    </thead> 
    <tbody> 
@foreach (var item in Model.Student) { 
        <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-page="./Edit" asp-route-id="@item.Id">Edit</a> | 
                <a asp-page="./Details" asp-route-id="@item.Id">Details</a> | 
                <a asp-page="./Delete" asp-route-id="@item.Id">Delete</a> 
            </td> 
        </tr> 
} 
    </tbody> 
</table>

Pour manipuler des données du code métier dans la vue, cette dernière doit disposer de la directive @Model, suivi du nom complet (vous devez tenir compte du namespace) de la classe qui hérite de PageModel :

Code c# : Sélectionner tout
@model RazorDemo.Pages.Students.IndexModel

Pour utiliser les propriétés de cette classe dans la vue, vous devez désormais utiliser la directive model. Par exemple, pour afficher le LastName du premier étudiant dans la liste, on va procéder comme suit :

Code c# : Sélectionner tout
model.Student[0].LastName

La suite du code utilise les HTML Helper pour afficher la liste des étudiants comme il se doit. Pour en savoir plus sur les HTML Helper. Vous pouvez consulter mon tutoriel sur Razor.

Pour afficher la page Index du dossier Students, vous devez saisir l’URL suivante dans le navigateur, pendant que votre application est en cours d’exécution : http://localhost:5000/Students. Ce qui donne le résultat suivant :


La page Create

Examinons maintenant les fichiers Create.cshtml et Create.cshtml.cs du dossier Pages/Students. Ouvrez le fichier Create.cshtml.cs. Ce dernier contient le code suivant :

Code c# : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class CreateModel : PageModel 
    { 
        private readonly RazorDemo.Models.RazorDemoContext _context; 
  
        public CreateModel(RazorDemo.Models.RazorDemoContext context) 
        { 
            _context = context; 
        } 
  
        public IActionResult OnGet() 
        { 
            return Page(); 
        } 
  
        [BindProperty] 
        public Student Student { get; set; } 
  
        public async Task<IActionResult> OnPostAsync() 
        { 
            if (!ModelState.IsValid) 
            { 
                return Page(); 
            } 
  
            _context.Student.Add(Student); 
            await _context.SaveChangesAsync(); 
  
            return RedirectToPage("./Index"); 
        } 
    }

Vous remarquez la présence de deux méthodes. La première (OnGet) sera appelée suite à une requête Get et permettra d'afficher le formulaire d'insertion.

La seconde (OnPostAsync) sera appelée suite à une requête Post et permettra d'enregistrer les informations contenues dans le formulaire. Une fois les données sauvegardées, l’utilisateur sera redirigé vers la page Students/index, qui affichera la liste des étudiants avec la nouvelle entrée. Mais, avant, les DataAnnotations que nous avons définis dans le modèle seront utilisés pour valider les données. En cas d’incohérence, le formulaire de création sera de nouveau affiché avec les messages d’erreurs de validation :


La propriété Student est décorée avec l’attribut [BindProperty].

Code c# : Sélectionner tout
1
2
[BindProperty] 
public Student Student { get; set; }

Cela va permettre, lors de l’envoi des informations contenues dans le formulaire via la requête HTTP Post, au framework ASP.NET Core de binder automatiquement celles-ci avec cette propriété.

Passons au fichier Create.cshtml :

Code cshtml : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@page 
@model RazorDemo.Pages.Students.CreateModel 
  
@{ 
    ViewData["Title"] = "Create"; 
} 
  
<h2>Create</h2> 
  
<h4>Student</h4> 
<hr /> 
<div class="row"> 
    <div class="col-md-4"> 
        <form method="post"> 
            <div asp-validation-summary="ModelOnly" class="text-danger"></div> 
            <div class="form-group"> 
                <label asp-for="Student.FirstName" class="control-label"></label> 
                <input asp-for="Student.FirstName" class="form-control" /> 
                <span asp-validation-for="Student.FirstName" class="text-danger"></span> 
            </div> 
            <div class="form-group"> 
                <label asp-for="Student.LastName" class="control-label"></label> 
                <input asp-for="Student.LastName" class="form-control" /> 
                <span asp-validation-for="Student.LastName" class="text-danger"></span> 
            </div> 
            <div class="form-group"> 
                <label asp-for="Student.Email" class="control-label"></label> 
                <input asp-for="Student.Email" class="form-control" /> 
                <span asp-validation-for="Student.Email" class="text-danger"></span> 
            </div> 
            <div class="form-group"> 
                <input type="submit" value="Create" class="btn btn-default" /> 
            </div> 
        </form> 
    </div> 
</div> 
  
<div> 
    <a asp-page="Index">Back to List</a> 
</div> 
  
@section Scripts { 
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} 
}

Des Tag Helpers sont utilisés pour mettre en place le formulaire. Pour en savoir plus sur les Tag Helpers vous pouvez consulter le billet de blog suivant : Introduction aux Tag Helpers.

C'est tout pour aujourd’hui. Dans le prochain billet, nous verrons comment mettre en place les tests unitaires pour une application ASP.NET Core Razor Pages. Le code source de l'application d'exemple de ce billet est disponible sur ma page GitHub.


Vous avez aimé cette actualité ? Alors partagez-la avec vos amis en cliquant sur les boutons ci-dessous :
Contacter le responsable de la rubrique Accueil