Créer une application web avec ASP.NET Core MVC

Temps approximatif : 2 heure et 0 minutes

Dans ce tutoriel nous allons créer une application web de gestion de voitures de collection en ASP.NET Core MVC avec un modèle, un contrôleur et des vues

Suivez le guide...

1 - Créer une application Web ASP.NET Core MVC

Ouvrez Visual Studio 2017 et créez un nouveau projet de type " Application web ASP.NET Core "


Dans la fenêtre qui suit choisissez le modèle "Application web (Model-View-Controller)"


Vous disposez maintenant d'une application web fonctionnelle créée selon le modèle MVC, cette application de base constitue un bon point de départ, Vous pouvez la tester : Ctrl-F5
Pour votre information :
L'architecture MVC sépare le programme en 3 couches: Modèle, Vue et Contrôleur.
- Le modèle contient des classes qui représentent les données de l'application
- La vue affiche l'interface utilisateur de l'application
- Les contrôleurs gèrent les demandes de l'utilisateur, récupèrent les données du modèle et appellent les vues qui retournent à l'utilisateur une réponse en fonction de ses entrées
>Préserver cette séparation de rôles permet de créer un code clair, testable et facile à gérer

Nous devons aussi comprendre le système de routage des requêtes dans ASP.NET Core
Une url comme https://localhost:1234/Toto/Blabla a comme données de routage "Toto" (le contrôleur) et "Blabla" (la méthode d'action à appeler sur le contrôleur "Toto").
https://localhost:1234/Voiture/Edite/55 est donc une demande de modification adressée au contrôleur "Voiture" pour lui demander de modifier la voiture 55

Le format de routage des requêtes est défini dans la méthode Configure() du fichier Startup.cs :
routes.MapRoute(
	name: "default",
	template: "{controller=Home}/{action=Index}/{id?}");
 

2 - Ajouter un contrôleur

Allez dans l'explorateur de solutions
Faites un clique droit sur Contrôleurs > Ajouter > Contrôleur
Choisissez "Contrôleur MVC - vide" dans la fenêtre qui suit

Tapez le nom du contrôleur: "VoituresController"


Collez le code suivant dans VoituresController.cs :
using Microsoft.AspNetCore.Mvc;
using System.Text.Encodings.Web;

namespace Voitures.Controllers
{
    public class VoituresController : Controller
    {
        public string Index()
        {
            return "Liste des voitures";
        }
        public string ListeCollectionneurs()
        {
            return "Liste des collectionneurs de vieilles voitures";
        }
    }
}
 

Dans votre navigateur tapez "https://localhost:44333/Voitures" dans la barre d'adresses
(remplacez 44333 par le bon numéro de port)
> Vous atterrirez sur la méthode d'action "Index" du contrôleur "Voitures" et vous obtiendrez comme réponse :
>> "Liste des voitures" <<


Tapez maintenant "https://localhost:44333/Voitures/ListeCollectionneurs"
> Vous atterrirez sur la méthode d'action "ListeCollectionneurs" du contrôleur "Voitures" et vous obtiendrez comme réponse :
>> "Liste des collectionneurs de vieilles voitures" <<


Nous voulons maintenant les collectionneurs de la marque de voitures Peugeot année 1975
Nous allons devoir passer deux arguments à la méthode ListeCollectionneurs() : marque et année :
public string ListeCollectionneurs(string marque, int annee)
{
	return $"Liste des collectionneurs de la voiture {marque} année {annee}";
}
 

Dans votre navigateur tapez maintenant : "https://localhost:44333/Voitures/ListeCollectionneurs?marque=peugeot&annee=1975"
> Vous devriez voir le message suivant :
>> Liste des collectionneurs de la voiture peugeot année 1975 <<


Jusqu'à maintenant nous avons demandé au contrôleur de retourner le résultat directement à l'utilisateur mais l'architecture MVC implique l'utilisation de vues pour bien séparer les rôles

3 - Ajouter une vue

Nous utiliserons Rasor pour créer un modèle de vue .cshtml
Allez dans le dossier "Views" et ajoutez un nouveau dossier que vous appellerez "Voitures"
Dans le dossier "Voitures" ajoutez un nouvel élément de type "Vue Razor"

Collez le code suivant dans Views/Voitures/Index.cshtml :
@{
    ViewData["Title"] = "Liste des collectionneurs";
}
<h2>Belle vue</h2>
<p>Liste des collectionneurs</p>
 

Pour charger cette vue nous allons modifier la méthode d'action Index du contrôleur VoituresController comme ceci :
public IActionResult Index()
{
	return View();
}
 

C'est tout ! Vous pouvez tester en appelant le contrôleur à l'adresse suivante :
https://localhost:44333/Voitures

La vue Index.cshtml a bien été chargée !

Nous allons maintenant ajouter une option "Liste" dans le menu principal de l'application
Ouvrez la page layout du site Views/Shared/_Layout.cshtml et ajoutez un lien href après le lien "Home" :
<ul class="nav navbar-nav">
	<li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
	<li><a asp-area="" asp-controller="Voitures" asp-action="Index">Liste</a></li>
	<li><a asp-area="" asp-controller="Home" asp-action="About">About</a></li>
	<li><a asp-area="" asp-controller="Home" asp-action="Contact">Contact</a></li>
</ul>
 

Vous avez remarqués les attributs "asp-controller" et "asp-action" dans les liens hrefs du menu ?
Si vous êtes un bon développeur csharp vous savez à quoi ils servent ...

Ces attributs disent simplement à MVC quelle méthode d'action exécuter sur quel contrôleur

Les Layouts vous permettent de spécifier votre HTML dans un emplacement unique une fois pour toute, puis de l'appliquer à plusieurs pages, MVC va chercher le fichier HTML de la vue demandée et va l'intégrer à l'emplacement de de la directive @RenderBody() du layout avant d'envoyer le résultat au navigateur

Voilà ! Notre application MVC a une vue "V" et un contrôleur "C", mais pas encore de modèle "M"

Dans une application MVC le contrôleur récupère les données d'une source de données à travers un modèle de données et détermine quelle vue envoyer au navigateur, les modèles de vue Razor ne doivent pas exécuter de logique métier

Avant de créer le modèle de données je vais vous présenter un ami: le dictionnaire ViewData car il est important que vous compreniez au moins un mécanisme de passage de données du contrôleur à la vue, secouez vous cher développeur csharp et ouvrez bien vos yeux...

4 - Passage de données à la vue depuis le contrôleur

Nous allons modifier la méthode d'action "ListeCollectionneurs" du contrôleur "VoituresController" :
public IActionResult ListeCollectionneurs(string marque, int annee)
{
	ViewData["Marque"] = marque;
	ViewData["Annee"] = annee;
	return View();
}
 

Le dictionnaire ViewData contient maintenant les données que nous voulons passer à la vue, à savoir : la marque et l'année
Dans le dossier "Voitures" ajoutez un nouvel élément de type "Vue Razor" et appelez-le : ListeCollectionneurs.cshtml
Collez dedans ceci :
@{
    ViewData["Title"] = "Liste des collectionneurs";
}
<h2>Liste des collectionneurs</h2>
<ul>
    @for (int i = (int)ViewData["annee"]; i <= DateTime.Now.Year - 20; i++)
    {
        <li>de <b>@ViewData["marque"]</b> année @i</li>
    }
</ul>
 

Exécutez la méthode d'action "ListeCollectionneurs" du contrôleur "Voitures" en lui passant les paramètres marque et année :
https://localhost:44333/Voitures/ListeCollectionneurs?marque=peugeot&annee=1975


Ça marche !

C'est bon pour la première partie.

>> Télécharger mon code source <<


Supprimez maintenant le contrôleur Voitures et les vues Index et ListeCollectionneurs, nous allons les générer automatiquement lors de la prochaine étape :
\Controllers\VoituresController.cs
\Views\Voitures\Index.cshtml
\Views\Voitures\ListeCollectionneurs.cshtml

Supprimez aussi l'entrée "Liste" du menu !

5 - Ajouter un modèle

Nous allons utiliser le framework de mapping relationnel d'objets: Entity Framework Core

Ajoutez une classe "Voiture.cs" dans le dossier Models (Ce sera notre modèle de données)
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace Voitures.Models
{
    public class Voiture
    {
        public int Id { get; set; }
        public string Nom { get; set; }
        public string Marque { get; set; }
        [Column(TypeName = "decimal(18, 2)")]
        public decimal Prix { get; set; }
        [Display(Name = "Date de fabrication")]
        [DataType(DataType.Date)]
        public DateTime DateFabrication { get; set; }
    }
}
 

Nous avons utilisé l'attribut DataType sur le champ DateFabrication pour spécifier le type de données Date au lieu de DateTime, l'utilisateur n'a pas besoin de saisir l'heure à laquelle la voiture a été fabriquée
L'attribut Display spécifie un nom alternatif à afficher pour le nom du champ (dans le cas présent, "Date de fabrication" au lieu de "DateFabrication").
L'attribut Column est nécessaire pour qu'Entity Framework Core puisse mapper le champ Prix en devise dans la base de données

Nous avons notre classe de définition, nous allons maintenant générer le modèle pour les opérations CRUD de base (création, lecture, mise à jour et suppression)

Dans l'explorateur de solutions faites un clique droit sur Contrôleurs > Ajouter > Nouvel élément généré automatiquement


Sélectionnez "Contrôleur MVC avec vues utilisant Entity Framework"

Renseignez les informations demandées dans la boîte de dialogue

Classe de modèle : Voiture (Voitures.Models)
Classe de contexte de données : Voitures.Models.VoituresDBContext
Nom du contrôleur : VoituresController

Go !

Visual Studio a créé :
- Une classe de contexte de données Entity Framework Core (Data/VoituresDBContext.cs)
- Un contrôleur (Controllers/VoituresController.cs)
- Des fichiers de vues Razor pour les opérations CRUD (Views/Voitures/*.cshtml)

Maintenant il faut ajouter une migration initiale
Attention : il faut ajouter la migration initiale seulement si la base de données n'existe pas c'est notre cas maintenant

Démarrez la "Console du gestionnaire de package"
Outils > Gestionnaire de package NuGet > Console du gestionnaire de package

Tapez les commandes suivantes à l'invite de commandes :
Add-Migration Initial
Update-Database


La commande Add-Migration va générer le code de création du schéma de la base de données, ce schéma est basé sur le modèle de données que vous avez spécifié dans la classe Voiture.cs


La commande Update-Database exécute la méthode Up() de la classe Migrations/###_InitialCreate.cs cela va entraîner la création de la base de données

Allez voir dans Startup.cs : le contexte de la base de données est inscrit au démarrage de l'application par un mécanisme d'injection de dépendances, il sera passé ultérieurement aux contrôleurs des pages Rasor qui en ont besoin
public void ConfigureServices(IServiceCollection services)
{
...
	services.AddDbContext<VoitureContext>(options =>
			options.UseSqlServer(Configuration.GetConnectionString("VoituresDBContext")));
}
 

La chaine de connexion sql est stockée dans appsettings.json

Allez voir VoituresController.cs
namespace Voitures.Controllers
{
    public class VoituresController : Controller
    {
        private readonly VoituresDBContext _context;
        public VoituresController(VoituresDBContext context)
        {
            _context = context;
        }
 

Le contexte de base de données a été passé au contrôleur car il sera utilisé dans chacune des méthodes CRUD

Examinez maintenant le contenu du fichier de vue : Views/Voitures/Index.cshtml :
@model IEnumerable<Voitures.Models.Voiture>
...
@foreach (var item in Model) {
 

L'instruction @model en haut du fichier de vue sert à spécifier le type d'objet attendu par la vue et permet d'accéder aux voitures que le contrôleur a passées à la vue en utilisant un objet fortement typé (Model)

Dans le menu Affichage, ouvrez l'Explorateur d'objets SQL Server et vérifiez que la base de données VoituresDBContext a bien été créée

Super ! la base de données a été créée
Si vous souhaitez la supprimer vous pouvez faire :
drop-database
remove-migration


(Ne le faites surtout pas)

6 - Peupler la base de données (facultatif)

Maintenant nous allons peupler la base de données avec une liste de voitures

Créez une classe SeedData.cs dans Models
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq;

namespace Voitures.Models
{
    public static class SeedData
    {
        public static void Initialize(IServiceProvider serviceProvider)
        {
            using (var context = new VoitureContext(
                serviceProvider.GetRequiredService<
                    DbContextOptions<VoitureContext>>()))
            {
                // Chercher n'importe quelle voiture.
                if (context.Voiture.Any())
                {
                    return;   // la base de données est déjà peuplée
                }

                context.Voiture.AddRange(
                    new Voiture
                    {
                        Nom = "Mustang",
                        Marque = "Ford",
                        Prix = 10000,
                        DateFabriquation = DateTime.Parse("1966-1-12")
                    },
                    new Voiture
                    {
                        Nom = "T",
                        Marque = "Ford",
                        Prix = 10000,
                        DateFabriquation = DateTime.Parse("1911-1-12")
                    },
                    new Voiture
                    {
                        Nom = "4L",
                        Marque = "Renault",
                        Prix = 10000,
                        DateFabriquation = DateTime.Parse("1968-1-12")
                    },
                    new Voiture
                    {
                        Nom = "1000",
                        Marque = "Sicma",
                        Prix = 10000,
                        DateFabriquation = DateTime.Parse("1968-1-12")
                    },
                    new Voiture
                    {
                        Nom = "Traction",
                        Marque = "Citroen",
                        Prix = 10000,
                        DateFabriquation = DateTime.Parse("1938-1-12")
                    }
                );
                context.SaveChanges();
            }
        }
    }
}
 

Remplacez la fonction main() de Program.cs par ceci :
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Voitures.Models;
public static void Main(string[] args)
{
	var host = CreateWebHostBuilder(args).Build();
	using (var scope = host.Services.CreateScope())
	{
		var services = scope.ServiceProvider;
		try
		{
			var context = services.GetRequiredService<VoitureContext>();
			context.Database.Migrate();
			SeedData.Initialize(services);
		}
		catch (Exception ex)
		{
			var logger = services.GetRequiredService<ILogger<Program>>();
			logger.LogError(ex, "Une erreur lors de la population de la base de données");
		}
	}
	host.Run();
}
 

Exécutez le programme
La base de données a été peuplée avec AddRange, si la base est déjà peuplée il ne se passera rien


Dans le menu Affichage, ouvrez l'Explorateur d'objets SQL Server et vérifiez que la base de données a bien été peuplée


Maintenant démarrez l'application : https://localhost:0000/Voitures
L'application affiche normalement les données de la base

Félicitations développeur csharp !
Vous savez maintenant travailler avec Entity Framework
Testez les liens Create, Edit, Details et Delete et admirez sa force !

Regardez la vidéo suivante pour vous rappeler des étapes ou Télécharger le code source


Commentaires
SnowNow a dit :
Très bon article. Clair et précis Merci et bonne continuation

mardi 16 avril 2019.



Laisser un commentaire
E-mail (obligatoire) (strictement confidentielle)

Nom (obligatoire)

Site web

Entrez votre commentaire...

Question de sécurité : Le ciel est ...






























Développé par Developpeur-Csharp.com
Mentions légales
Testé et compatible, à partir de : Firefox 3, Internet Explorer 7.0, Safari 4, Chrome, et Opera 9.
















Newsletter
Abonnez-vous à ma newsletter pour ne rater aucun article !
Adresse mail :

Discussion
Instantanée