Architecture MVC
Introduction
Dans une application Web, afficher une page, préparer les données qui seront affichées et exécuter une règle métier correspondent à trois traitements différents. Lorsque ces traitements se retrouvent mélangés, une modification de l’interface peut impacter le code métier, et les tests deviennent plus difficiles à cibler. Le modèle MVC (Model–View–Controller, ou modèle–vue–contrôleur) est une solution permettant de mieux répartir ces traitements.
Avec ASP.NET Core MVC, ce modèle prend la forme de contrôleurs C#, de vues Razor et de classes C# correspondant à des modèles adaptés aux données et aux traitements de l’application.
Qu’est-ce que l’architecture MVC ?
MVC est un modèle d’organisation de l’interface et des interactions. Il distingue trois rôles :
| Composant | Rôle | Exemple avec ASP.NET Core MVC |
|---|---|---|
| Modèle | Porte les données et les règles utiles au traitement. Le terme peut aussi désigner un modèle de présentation propre à une vue (ViewModel) : ces objets n’ont pas forcément la même responsabilité. | Une entité Produit, un service métier ou un ProduitDetailsViewModel. |
| Vue | Produit la représentation envoyée au navigateur. Elle contient surtout du code de présentation. | Un fichier Razor Details.cshtml. |
| Contrôleur | Reçoit la requête, coordonne le traitement et choisit la réponse à retourner. | Une action Details dans ProduitsController. |
Voici un schéma permettant d'expliciter l'affichage de la fiche d’un produit, dans une application développée avec ASP .NET Core MVC :
Dans une application ASP.NET Core MVC classique, le routage sélectionne une action du contrôleur. Celui-ci obtient les données nécessaires, prépare un modèle de présentation (ViewModel) et renvoie une vue Razor qui s'alimente avec ce modèle. La vue génère alors le code HTML / CSS/ JS de la réponse. Pour une saisie, la liaison des modèles convertit les valeurs de la requête en types .NET, puis la validation aide à signaler les données incorrectes.
Attention au mot « modèle » : MVC n’impose pas que toutes les règles métier résident dans une classe placée dans un dossier Models. Dans une application plus riche, les règles peuvent être définies dans un domaine ou des services applicatifs. Les ViewModels servent à fournir à chaque vue les données dont elle a besoin.
Un simple exemple en C#
Une application s'exécutant dans un navigateur Web envoie à l'application Web, une requête HTTP dont l'URL est /Produits/Details/79. Le routage dirige la demande vers l'action Details du contrôleur ProduitsController avec la valeur 42 en paramètre. Le contrôleur appelle un service qui recherche le produit, construit un objet de type ProduitDetailsViewModel, puis demande à la vue Details.cshtml de produire la page HTML. Si le produit n’est pas trouvé, une réponse HTTP 404 est renvoyée :
public record ProductDetailsViewModel(int Id, string Nom, decimal Prix);
public interface IProduitService
{
Task<ProductDetailsViewModel?> ObtenirDetailsAsync(
int id,
CancellationToken cancellationToken);
}
public class ProductsController : Controller
{
private readonly IProduitService _products;
public ProductsController(IProduitService products)
{
_products = products;
}
[HttpGet]
public async Task<IActionResult> Details(
int id,
CancellationToken cancellationToken)
{
var product = await _products.GetDetailsAsync(
id, cancellationToken);
return produit is null ? NotFound() : View(product);
}
}
La vue correspondante affiche les données, sans effectuer elle-même la recherche du produit :
Ce simple exemple met en relief la répartition des rôles. L’implémentation de IProductService et son enregistrement dans l’injection de dépendances restent à fournir dans une application complète (API).
Les avantages
Des responsabilités identifiables
Les contrôleurs traitent les requêtes, choisissent la vue qui présente les résultats et le modèle fournit les données et comportements nécessaires.
Des tests mieux ciblés
Les règles métier et les actions des contrôleurs peuvent être vérifiées séparément lorsque leurs dépendances sont explicites.
Une présentation plus facile à faire évoluer
Une vue peut changer sans réécrire les règles métier si les responsabilités sont bien réparties.
Un cadre familier avec ASP.NET Core
Le routage, la liaison des modèles, la validation, l’injection de dépendances et Razor facilitent la création d’interfaces Web structurées.
Les limites
Un découpage parfois disproportionné
Pour quelques pages simples, multiplier contrôleurs, modèles de présentation et vues peut alourdir la lecture du code.
Des contrôleurs qui peuvent grossir
Sans frontières claires, les actions finissent par contenir validation métier, accès aux données et orchestration, pouvant complexifier le code.
Des modèles aux rôles confondus
Réutiliser partout une entité EF Core pour la saisie, le métier et l’affichage peut créer des dépendances et exposer trop de données (d'où l'intervention des ViewModels).
Un périmètre architectural limité
MVC organise les interactions Web, mais ne définit pas à lui seul les frontières métier, la persistance ou le déploiement.
Quand cette architecture est-elle pertinente ?
MVC convient à une application Web rendue côté serveur, qui propose plusieurs pages proposant des traitements. Il est également adapté lorsqu’une équipe veut distinguer clairement le traitement des requêtes, la logique métier et la génération du code HTML, tout en profitant du langage Razor et de l’écosystème ASP.NET Core.
Pour une application centrée sur quelques pages indépendantes, Razor Pages peut offrir une organisation plus directe. Une application qui expose principalement des données à un client mobile ou à une interface JavaScript peut utiliser des API ASP.NET Core sans vues Razor. Le choix dépend de l’interface à produire et des parcours utilisateurs ; ces approches peuvent aussi coexister au sein d'une même application.
Bonnes pratiques avec .NET
Garder les contrôleurs légers
Confier les règles métier à des composants dédiés et limiter chaque action à la coordination de la requête et de la réponse.
Utiliser des modèles adaptés aux vues
Créer des ViewModels pour fournir uniquement les données nécessaires à l’affichage ou à la saisie.
Valider les entrées côté serveur
Vérifier les données reçues et appliquer les règles métier même si le navigateur effectue déjà une validation.
Sécuriser les actions
Contrôler les autorisations et protéger les formulaires authentifiés qui modifient des données contre les requêtes intersites.
Déclarer les dépendances explicitement
Injecter les services nécessaires dans les contrôleurs et isoler les accès EF Core dans les composants qui les utilisent.
Tester chaque niveau
Tester les règles métier isolément, puis vérifier les routes, les vues et la persistance dans les parcours importants.
