Le routage et les erreurs
Introduction
Le routage est un sujet très important en développement web. En effet, les routes sont la base de la navigation pour un site web, et pour tout l’Internet de manière générale. Les routes définissent en quelque sorte le chemin que vont pouvoir emprunter les utilisateurs finaux afin de naviguer à travers le site. Ces routes doivent être claires et précises afin de représenter au mieux le contenu de la page.
Le routage consiste simplement à associer une requête HTTP à un gestionnaire de route. Ce gestionnaire va ensuite s’occuper de traiter la route en fonction de son implémentation. Les routes sont définies au démarrage de l’application, et cette section expose plusieurs moyens permettant de configurer les routes. Le routage est également en charge de la génération des liens permettant par exemple des redirections.
Ce chapitre traitera de la problématique du routage et exposera les différentes API responsables du traitement des requêtes HTTP et des routes. Le routage via ASP.NET Core permet de mettre en œuvre une multitude de fonctionnalités qui seront expliquées dans les sections suivantes. Pour finir, le chapitre traitera de la gestion des erreurs et des pages d’exceptions au sein d’un projet ASP.NET Core.
La gestion des URL
Le processus de détermination d’une route est simple. En général, une application web ne comporte qu’une seule collection de routes. Afin de déterminer quelle route il faut emprunter selon la requête, le site va parcourir toutes les routes, et via un système de correspondance va déterminer la première route capable de répondre à la requête.
Avec ASP.NET Core, il existe deux composants importants dans la gestion des routes :
-
L’interface IRouter, qui détermine si la requête correspond à l’une des routes enregistrées dans l’application.
-
Le middleware RouteMiddleware, qui va lancer l’appel vers le processus de détermination d’une route. Si une route est trouvée, le processus continue vers le composant en charge du traitement de la requête selon la route bien spécifique. Sinon, le middleware continue de chaîner les appels des middlewares.
De manière synthétique, le middleware appelle la méthode RouteAsync de IRouter sur toutes les routes afin de déterminer laquelle est la plus adaptée. La classe responsable de déterminer si la requête correspond à une route est la classe TemplateMatcher via la méthode TryMatch.
Étant assez complexe, cette section ne traitera pas en détail la méthode TryMatch car ce n’est pas l’objet de ce chapitre. Cependant, il est intéressant de scruter rapidement l’enchaînement...
Le middleware et les contraintes
Chaque requête est traitée via un unique middleware de routage intitulé RouterMiddleware. Ce dernier va ainsi rediriger la requête vers un handler qui va traiter la requête. Son code est très simple :
public async Task Invoke(HttpContext httpContext)
{
var context = new RouteContext(httpContext);
context.RouteData.Routers.Add(_router);
await _router.RouteAsync(context);
if (context.Handler == null)
{
_logger.RequestDidNotMatchRoutes();
await _next.Invoke(httpContext);
}
else
{
httpContext.Features[typeof(IRoutingFeature)] = new
RoutingFeature()
{
RouteData = context.RouteData,
};
await context.Handler(context.HttpContext);
}
}
La première partie du middleware permet la création d’un objet de contexte pour la gestion du routage de type RouteContext. C’est cet objet qui va être modifié dans le processus de détermination d’une route, et qui va contenir la suite des opérations (si une route est trouvée) via sa propriété Handler de type RequestDelegate.
var context = new RouteContext(httpContext);
context.RouteData.Routers.Add(_router);
L’objet déterminant le routage qui est injecté, symbolisé par la propriété _router, est par défaut la classe Router, implémentant IRouter, qui permet de déterminer la route.
Ensuite, le middleware appelle simplement la méthode RouteAsync() permettant de trouver la bonne route pour la requête entrante. Cette dernière va ainsi, pour chaque route enregistrée, vérifier que le template correspond à la requête demandée via la classe TemplateMatcher.
await _router.RouteAsync(context);
À ce moment précis, la classe Route, héritant de RouteBase pour...
Les pages d’erreur
Les erreurs et les exceptions sont des éléments courants en programmation informatique, et ASP.NET Core ne déroge pas à la règle. Le système n’est jamais à l’abri, et le développeur doit disposer de tous les outils nécessaires afin de gérer au mieux les cas d’erreurs.
Dans un premier temps, il est possible pour le développeur de configurer une page d’exception qui va s’afficher lorsqu’une erreur survient sur le site. Cette page, conçue spécialement pour le débogage et à utiliser uniquement lors de la phase de développement du site, permet de visualiser plusieurs informations utiles afin de cibler le problème. Le code ci-dessous configure cette page dans la classe Startup.
public void Configure(IApplicationBuilder app,
IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
Deux choses sont importantes ici :
-
Le test permettant de vérifier que l’environnement du système est en développement (modifiable dans les paramètres du projet).
-
La méthode UseDeveloperExceptionPage permettant d’afficher une page d’exception lorsqu’une erreur survient dans le code.
Encore une fois, cette page ne doit être utilisée qu’en mode développement, car elle est susceptible d’afficher des informations sensibles sur le site.
Afin de tester cette page, c’est très simple : il suffit de lever une exception dans n’importe quelle partie du code :
throw new Exception("Exception triggered!");
Lorsque le code lève une exception, le serveur redirige automatiquement vers la page d’erreur, fournissant ainsi plusieurs informations de débogage.
Page d’exception pour les développeurs
Les informations contenues dans cette page d’exception sont :
-
La pile d’exécution : affichage de la pile d’exécution du code qui a été appelé, avec un zoom sur la ligne qui a levé l’exception, le fichier qui contient le code, la ligne et ainsi de suite.
-
La requête : affichage de la requête qui a été...