đ .NET (ASP.NET Core) â Le Guide Ultime
Deep Dive : C#, ASP.NET Core (Middleware, DI), EF Core (ORM), Web API, Blazor & Outils (NuGet).
1. C'est quoi .NET ?
Framework open-source, cross-platform (Linux, Win, macOS). .NET Core vs .NET 8+.
.NET C#2. Langage C# (Core)
Typage statique, POO. { get; set; }, LINQ, async/await (Task).
3. ASP.NET Core (Intro)
Le framework web. Program.cs, Kestrel (serveur web), Minimal APIs.
4. Pipeline Middleware
Le "cĆur" d'ASP.NET. L'oignon. app.Use..., RequestDelegate.
5. đ Dependency Injection (DI)
Inversion de contrĂŽle (IoC). AddSingleton, AddScoped, AddTransient.
6. Framework : Web API (REST)
[ApiController], [HttpGet], ActionResult<T>, Ok(), NotFound().
7. Framework : MVC
Model, View (Razor, .cshtml), Controller. Le pattern "classique".
8. Framework : Blazor
C# dans le navigateur (WebAssembly). Blazor Server vs Blazor WASM.
Blazor WASM9. đŸ Data : EF Core (ORM)
Entity Framework. DbContext, DbSet<T>, LINQ to SQL, Migrations.
10. Sécurité (Identity & JWT)
AuthN (Identity) vs AuthZ ([Authorize]). Cookies vs JWT Bearer (APIs).
11. Outils : dotnet CLI & NuGet
dotnet new, run, add package. NuGet (le "npm/pip" de .NET).
12. Plugins & ĂcosystĂšme
Déploiement (Azure), Addons (Serilog, Polly, AutoMapper). Liens.
Azure Docker.NET est un framework de développement gratuit, open-source et multi-plateforme (Linux, macOS, Windows) créé par Microsoft. Il permet de construire tout type d'applications (Web, Mobile, Desktop, Cloud, IA, IoT).
.NET Framework vs .NET Core vs .NET 8
C'est la confusion la plus fréquente :
- .NET Framework (Legacy) : L'original (2002-2019). Windows uniquement. C'est l'ancien monde (
System.Web,.aspx). Il est maintenant en mode maintenance. - .NET Core (2016) : La ré-écriture. Open-source, cross-platforme, et rapide. C'est la fondation de tout ce qui est moderne (ASP.NET Core, EF Core).
- .NET 5, 6, 7, 8... (Aujourd'hui) : L'unification. Microsoft a abandonné le nom "Core" à partir de .NET 5. ".NET 8" est la version moderne et unifiée de ".NET Core".
L'ĂcosystĂšme (Langages & Runtime)
| Composant | Description |
|---|---|
| Langages | C# (C-Sharp) (le principal : POO, typé statique), F# (fonctionnel), VB.NET (legacy). |
| Runtime (CLR) | Le CoreCLR (Common Language Runtime). GÚre la mémoire (Garbage Collector), la sécurité, et exécute le code CIL (Common Intermediate Language). |
| SDK & CLI | Le SDK (Software Development Kit) et l'outil dotnet (CLI) pour créer, builder, et lancer des projets. |
| Frameworks | ASP.NET Core (Web), Entity Framework Core (Data), MAUI (Mobile/Desktop), ML.NET (IA). |
C# (C-Sharp) est le langage principal de .NET. C'est un langage moderne, orienté objet et statiquement typé (similaire à Java ou TypeScript).
Syntaxe de Base
// 1. Typage Statique
string nom = "Alice";
int age = 30;
// nom = 123; // Erreur de compilation !
// 2. Inférence de type (mot-clé 'var')
var prenom = "Bob"; // Le compilateur 'devine' que c'est un string
var score = 10.5; // Le compilateur 'devine' que c'est un double
// 3. POO (Classes & Propriétés auto)
public class Utilisateur
{
// Propriétés auto (getter + setter)
public int Id { get; set; }
public string Nom { get; set; }
}
Les 2 "Killer Features" de C#
1. LINQ (Language-Integrated Query)
Permet d'Ă©crire des requĂȘtes (type SQL) directement dans le code C# pour interroger n'importe quelle collection (Listes, XML, BDD...).
List<int> nombres = new() { 1, 5, 10, 15, 20 };
// Syntaxe "Méthode" (la plus courante)
var grandsNombres = nombres
.Where(n => n > 8)
.OrderByDescending(n => n)
.Select(n => n * 2);
// (Résultat: [40, 30, 20])
// Syntaxe "Query" (type SQL)
var grandsNombresSQL = from n in nombres
where n > 8
orderby n descending
select n * 2;
2. async / await (Asynchronisme)
Rend le code asynchrone (non-bloquant) aussi facile Ă lire que du code synchrone. Le C# utilise Task<T> (similaire aux Promise JS).
// 'async' dit au compilateur que cette méthode est asynchrone
// 'Task<string>' est la "promesse" d'un futur string
public async Task<string> GetDataFromApiAsync()
{
var client = new HttpClient();
// 'await' "déballe" la Task sans bloquer le thread
var response = await client.GetAsync("https://api.example.com");
response.EnsureSuccessStatusCode();
string content = await response.Content.ReadAsStringAsync();
return content;
}
ASP.NET Core est le framework web de .NET. Il est conçu pour ĂȘtre modulaire, lĂ©ger et haute-performance.
Il tourne sur Kestrel, un serveur web cross-platform ultra-rapide (souvent derriĂšre un reverse proxy comme Nginx ou IIS).
La révolution : Program.cs (Minimal APIs)
Depuis .NET 6 (2021), l'ancien Startup.cs a disparu. Toute l'application est configurée dans un seul fichier Program.cs, ce qui le rend trÚs similaire à Flask (Python) ou Express (Node.js).
Exemple : Un "Hello World" en Minimal API (Program.cs)
// 1. Créer le "builder" d'application
var builder = WebApplication.CreateBuilder(args);
// (C'est ici qu'on ajoute les services, voir DI 1.5)
// 2. Construire l'application
var app = builder.Build();
// 3. Configurer le "pipeline" (voir Middleware 1.4)
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// 4. Définir un endpoint (une route)
app.MapGet("/", () => "Hello World!");
app.MapGet("/users/{id}", (int id) => {
// Logique...
return Results.Ok(new { UserId = id, Name = "Alice" });
});
// 5. Lancer le serveur Kestrel
app.Run();
Le cĆur d'ASP.NET Core est le Pipeline Middleware. C'est une "chaĂźne" (ou un "oignon") de composants qui traitent une requĂȘte HTTP.
Chaque requĂȘte passe Ă travers ce pipeline. Chaque middleware peut inspecter la requĂȘte, la modifier, ou y rĂ©pondre (court-circuiter).
Program.cs (Configuration du Pipeline)
L'ordre est CRUCIAL. Une requĂȘte "descend" (app.Use...) puis "remonte".
var app = builder.Build();
// 1. Middleware de gestion d'erreurs (le plus haut)
app.UseExceptionHandler("/Error");
// 2. Middleware de fichiers statiques (ex: css, js, img)
// (Il répond et court-circuite s'il trouve un fichier)
app.UseStaticFiles();
// 3. Middleware de Routage (il "décide" quel endpoint sera appelé)
app.UseRouting();
// 4. Middleware d'Authentification (QUI est l'utilisateur ?)
app.UseAuthentication();
// 5. Middleware d'Autorisation (Qu'a-t-il le DROIT de faire ?)
app.UseAuthorization();
// 6. "Endpoints" (la fin du pipeline)
app.MapControllers(); // (Pour MVC / Web API)
app.MapRazorPages(); // (Pour Razor Pages)
app.MapGet("/", () => "Hello"); // (Pour Minimal API)
app.Run();
Ăcrire un Middleware "inline" (custom)
// 'RequestDelegate next' est le *prochain* middleware dans la chaĂźne
app.Use(async (context, next) =>
{
// --- Code "Request" (avant l'endpoint) ---
var timer = Stopwatch.StartNew();
// 2. Appelle le reste du pipeline
await next(context);
// --- Code "Response" (aprĂšs l'endpoint) ---
timer.Stop();
Console.WriteLine($"RequĂȘte {context.Request.Path} traitĂ©e en {timer.ElapsedMilliseconds}ms");
});
L'Injection de Dépendances (DI) est un principe fondamental (le "D" de SOLID) qui est intégré nativement dans ASP.NET Core. C'est un conteneur "Inversion of Control (IoC)".
L'idĂ©e : Au lieu qu'une classe (ex: MonController) ne crĂ©e *elle-mĂȘme* ses dĂ©pendances (ex: new MonService()), elle les *demande* dans son constructeur. Le "conteneur DI" se charge de les crĂ©er et de les injecter.
1. Enregistrer les Services (dans Program.cs)
On "enseigne" au conteneur comment résoudre une "Interface" (IMyService) avec une "Classe" (MyService). C'est là que l'on choisit le "Cycle de Vie" (Lifetime).
| Lifetime (Cycle de Vie) | Description |
|---|---|
.AddSingleton() | Un seul objet pour toute l'application. (Créé la 1Úre fois, puis réutilisé par tout le monde). (Pour : Caches, Configs). |
.AddScoped() | Un objet par requĂȘte HTTP. (Le plus courant). Tous les services d'une mĂȘme requĂȘte partagent la mĂȘme instance. (Pour : DbContext EF Core, Services mĂ©tier). |
.AddTransient() | Un nouvel objet à chaque fois qu'il est demandé. (Pour : Services trÚs légers, sans état). |
2. Le Code (Program.cs & Controller)
/* --- 1. Program.cs (Enregistrement) --- */
var builder = WebApplication.CreateBuilder(args);
// On dit au DI: "Si quelqu'un demande 'IMyService',
// crĂ©e une instance 'MyService', et garde-la pour la requĂȘte (Scoped)."
builder.Services.AddScoped<IMyService, MyService>();
builder.Services.AddTransient<IEmailService, EmailService>();
builder.Services.AddSingleton<IAppConfig, AppConfig>();
builder.Services.AddControllers();
// ...
/* --- 2. MyController.cs (Injection) --- */
// (Le "Controller" demande les services dont il a besoin)
[ApiController]
[Route("api/[controller]")]
public class MyController : ControllerBase
{
// 2a. Dépendances
private readonly IMyService _service;
private readonly IEmailService _email;
// 2b. Injection par Constructeur (le DI remplit ça)
public MyController(IMyService service, IEmailService email)
{
_service = service;
_email = email;
}
[HttpGet]
public IActionResult Get()
{
// 2c. Utilisation
var data = _service.GetData();
return Ok(data);
}
}
ASP.NET Core est l'outil n°1 pour construire des APIs REST performantes. On utilise le pattern "Controller".
Anatomie d'un ContrĂŽleur API
[ApiController]: Attribut qui active des "opinions" pour les APIs (ex: validation auto du modÚle, binding JSON).[Route]: Définit l'URL de base ([controller]est un token remplacé par le nom de la classe, ex: "Products").: ControllerBase: Classe de base qui fournit les méthodes "helper" (Ok(),NotFound()).[Http...]: Attributs qui lient une méthode à un verbe HTTP.IActionResult/ActionResult<T>: Types de retour qui permettent de renvoyer des Status Codes (200, 404) avec des données.
Exemple : ProductsController.cs (CRUD)
[ApiController]
[Route("api/[controller]")] // -> /api/products
public class ProductsController : ControllerBase
{
// (Le DbContext est injecté par DI, voir 1.5 & 3.1)
private readonly AppDbContext _context;
public ProductsController(AppDbContext context) { _context = context; }
// GET: /api/products
[HttpGet]
public async Task<ActionResult<IEnumerable<Product>>> GetProducts()
{
return Ok(await _context.Products.ToListAsync());
}
// GET: /api/products/5
[HttpGet("{id}")]
public async Task<ActionResult<Product>> GetProduct(int id)
{
var product = await _context.Products.FindAsync(id);
if (product == null)
{
return NotFound(); // Renvoie 404
}
return Ok(product); // Renvoie 200
}
// POST: /api/products
[HttpPost]
public async Task<ActionResult<Product>> CreateProduct(Product product)
{
_context.Products.Add(product);
await _context.SaveChangesAsync();
// Renvoie 201 Created + Header "Location: /api/products/5"
return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
}
}
MVC est le pattern "traditionnel" d'ASP.NET pour construire des applications web (pas des APIs) qui rendent du HTML cÎté serveur.
[Image of Model-View-Controller diagram]1. Model
Un "POCO" (Plain Old C# Object). Représente les données.
// Models/UserViewModel.cs
public class UserViewModel
{
public string Name { get; set; }
public bool IsAdmin { get; set; }
}
2. Controller
Reçoit la requĂȘte, parle au modĂšle, et choisit la vue.
// Controllers/UserController.cs
public class UserController : Controller
{
public IActionResult GetUser(int id)
{
// (Logique BDD...)
var model = new UserViewModel
{
Name = "Alice",
IsAdmin = true
};
// Renvoie la vue "GetUser.cshtml"
// et lui passe le 'model'
return View(model);
}
}
3. View (Razor)
Le template HTML (.cshtml). Utilise la syntaxe Razor (@).
@* Views/User/GetUser.cshtml * @
@* 1. Définit le type du ModÚle (typage fort) * @
@model UserViewModel
<h1>Détail de l'utilisateur</h1>
<!-- 2. Affiche les données du modÚle -->
<h2>@Model.Name</h2>
<!-- 3. Logique (if, for...) -->
@if (Model.IsAdmin)
{
<p class="text-danger">Cet utilisateur est Admin.</p>
}
MVC est puissant, mais peut ĂȘtre lourd. ASP.NET Core propose deux alternatives modernes.
1. Razor Pages
C'est le "nouveau MVC" (introduit en 2017). Il est Page-Centric (centré sur la page), pas Controller-Centric. C'est plus simple pour les applications basées sur les formulaires (ex: un back-office).
- Il n'y a plus de dossier "Controllers" et "Views".
- Chaque page est un couple de fichiers :
-Page.cshtml(Le HTML / Razor)
-Page.cshtml.cs(Le "Code-Behind", appelé PageModel) - Le
PageModelgĂšre les verbes HTTP (OnGet(),OnPost()).
2. Blazor (La Révolution)
Permet d'écrire des applications web interactives (SPA) en C# au lieu de JavaScript. Blazor utilise des "Composants" (.razor) réutilisables, comme React ou Vue.
Il existe deux modes de hosting :
| Mode | Comment ça marche ? | Avantages | Inconvénients |
|---|---|---|---|
| Blazor Server | Le C# tourne sur le serveur. L'UI (le DOM) est envoyée au client. Les interactions (clics) sont renvoyées au serveur via WebSocket (SignalR). Le serveur re-calcule le DOM et renvoie le "diff". | Léger (pas de .NET à télécharger). C# a accÚs à tout (BDD, ...). | Haute latence (chaque clic = aller-retour). Ne marche pas offline. |
| Blazor WebAssembly (WASM) | Le C# tourne dans le navigateur. L'application (et le runtime .NET) est compilée en WebAssembly (WASM) et téléchargée par le client. | Ultra-rapide (pas de latence). Fonctionne offline (PWA). | Téléchargement initial lourd (le runtime .NET). AccÚs BDD via API (pas direct). |
Entity Framework (EF) Core est l'ORM (Object-Relational Mapper) officiel de .NET. Il permet de manipuler une base de donnĂ©es (SQL Server, PostgreSQL, MySQL, SQLite...) en utilisant des objets C# et des requĂȘtes LINQ.
1. Le ModÚle (L'Entité)
Une simple classe C# ("POCO") qui représente une table.
public class User
{
public int Id { get; set; } // (Par convention, 'Id' est la clé primaire)
public string Username { get; set; }
public string Email { get; set; }
}
2. Le Contexte (La Session BDD)
Le DbContext est la "session" avec la BDD. On y déclare les "tables" (DbSet).
public class ApplicationDbContext : DbContext
{
// Constructeur (pour la DI)
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
// "Table" des Utilisateurs
public DbSet<User> Users { get; set; }
}
3. L'Utilisation (LINQ to SQL)
GrĂące Ă la DI, on injecte le DbContext dans nos services/controllers pour l'utiliser avec LINQ.
// (Injecté dans le constructeur)
private readonly ApplicationDbContext _context;
// LIRE (GET)
public async Task<User> GetUser(int id)
{
// EF Core traduit ce LINQ en "SELECT * FROM Users WHERE Id = ..."
return await _context.Users.FindAsync(id);
}
// CRĂER (POST)
public async Task CreateUser(string name)
{
var newUser = new User { Username = name };
_context.Users.Add(newUser);
await _context.SaveChangesAsync(); // Exécute le "INSERT"
}
4. Migrations (Outil CLI)
EF Core gÚre l'évolution du schéma de la BDD (Code-First).
# 1. Installer l'outil CLI $ dotnet tool install --global dotnet-ef # 2. Créer une "migration" (aprÚs avoir changé le ModÚle C#) $ dotnet ef migrations add AjoutColonneEmail # 3. Appliquer la migration à la BDD $ dotnet ef database update
ASP.NET Core a un systĂšme d'authentification (AuthN) et d'autorisation (AuthZ) robuste.
- Authentification (AuthN) : "Qui ĂȘtes-vous ?" (Login/Password, Token JWT).
- Autorisation (AuthZ) : "Avez-vous le droit ?" (RĂŽles, Policies).
1. ASP.NET Core Identity (La "Batterie Incluse")
Pour les applications web (MVC, Razor Pages), Identity est la solution par défaut. C'est un systÚme complet qui gÚre :
- La BDD (Tables
AspNetUsers,AspNetRoles...). - Les services (
UserManager,SignInManager). - L'authentification par Cookie.
2. Tokens JWT (Pour les Web APIs)
Les APIs (surtout REST) doivent ĂȘtre stateless (voir 1.4). On n'utilise pas de cookies de session. On utilise des JWT (JSON Web Tokens).
Flux (Simplifié) :
- Client
POST /api/token(envoie user/pass). - Serveur vérifie, génÚre un Token JWT (string chiffré) et le renvoie.
- Client stocke ce token (ex:
localStorage). - Pour *chaque* requĂȘte suivante, le client envoie le token dans le header :
Authorization: Bearer eyJhbGciOi... - Le middleware
app.UseAuthentication()intercepte ce token, le valide, et attache l'identitĂ© (User) Ă la requĂȘte.
3. Autorisation ([Authorize])
Une fois authentifié, on protÚge les endpoints avec des attributs.
[ApiController]
[Route("api/[controller]")]
public class DataController : ControllerBase
{
// Accessible par tout le monde
[HttpGet("public")]
[AllowAnonymous]
public IActionResult GetPublicData() { ... }
// Accessible SEULEMENT aux utilisateurs connectés
[HttpGet("private")]
[Authorize]
public IActionResult GetPrivateData() { ... }
// Accessible SEULEMENT aux utilisateurs connectés
// ET qui ont le RĂŽle "Admin"
[HttpGet("admin")]
[Authorize(Roles = "Admin")]
public IActionResult GetAdminData() { ... }
}
1. NuGet (Le Gestionnaire de Packages)
NuGet est le gestionnaire de packages de .NET (l'équivalent de npm, pip, ou Maven). Il gÚre les dépendances (les "plugins").
- DépÎt :
NuGet.org(le dépÎt central). - Fichier : Les dépendances sont listées dans le fichier
.csproj(XML).
2. dotnet CLI (L'outil principal)
L'interface en ligne de commande dotnet est l'outil unifié pour tout faire (remplace les anciens msbuild, nuget.exe...).
| Commande | Description |
|---|---|
dotnet --version | Vérifie la version du SDK. |
dotnet new list | Liste tous les "templates" (projets) disponibles. |
dotnet new webapi -n MyApi | Crée un nouveau projet d'API Web dans le dossier "MyApi". |
dotnet new mvc | Crée un projet ASP.NET MVC. |
dotnet add package Serilog | Ajoute le package "Serilog" (depuis NuGet) au projet (.csproj). |
dotnet restore | Restaure/télécharge tous les packages listés dans le .csproj. |
dotnet build | Compile le code (C# -> CIL). |
dotnet run | Compile (si besoin) et lance l'application. |
dotnet watch run | Lance l'app et la redémarre auto (hot-reload) si un fichier change. |
dotnet test | Lance les tests (xUnit, NUnit) du projet. |
dotnet publish -c Release | Compile l'app pour la production (optimisée) dans le dossier /bin/Release/.../publish. |
L'écosystÚme .NET est mature et rempli de librairies (plugins NuGet) de haute qualité pour les tùches courantes.
Plugins (Librairies) Incontournables
| Package NuGet | Description |
|---|---|
Serilog / NLog | Logging structuré. Beaucoup plus puissant que le ILogger natif. Permet d'écrire les logs en JSON vers des "sinks" (fichiers, cloud, BDD). |
Polly | Résilience. Permet d'implémenter facilement des "patterns" complexes : Retry (ré-essayer un appel API raté), Circuit Breaker (couper le circuit si une API est HS). |
AutoMapper | Mappage Objet-Objet. Automatise la conversion User (ModĂšle BDD) -> UserDto (ModĂšle API). |
MediatR | Implémentation du pattern "Mediator" (CQRS). Permet de découpler la logique en Query (lecture) et Command (écriture). |
Dapper | Un "Micro-ORM". L'alternative ultra-rapide à EF Core. Permet d'écrire du SQL brut et de le mapper à des objets C#. |
Newtonsoft.Json | (Legacy) L'ancien parseur JSON. (System.Text.Json est maintenant natif et plus rapide, mais Newtonsoft reste trÚs utilisé). |
Déploiement & Hébergement
dotnet publish: La commande qui prépare l'application pour la production (optimisée).- Azure : Le cloud de Microsoft. L'intégration est native et la plus simple (Azure App Service, Azure Functions).
- Docker : Microsoft fournit des images Docker officielles (
mcr.microsoft.com/dotnet/aspnet) pour conteneuriser et déployer sur Linux (ex: Kubernetes). - IIS (Windows) : (Legacy) Le serveur web de Windows. Fonctionne toujours, mais Kestrel est le standard.
