Traitement des exceptions non gérées (C#)
par Scott Mitchell
Affichez ou téléchargez l’exemple de code (procédure de téléchargement)
Lorsqu’une erreur d’exécution se produit sur une application web en production, il est important d’avertir un développeur et de consigner l’erreur afin qu’elle puisse être diagnostiquée ultérieurement. Ce tutoriel fournit une vue d’ensemble de la façon dont ASP.NET traite les erreurs d’exécution et examine une façon d’exécuter du code personnalisé chaque fois qu’une exception non prise en charge s’affiche dans le ASP.NET runtime.
Introduction
Lorsqu’une exception non prise en charge se produit dans une application ASP.NET, elle s’affiche jusqu’à l’ASP.NET runtime, ce qui déclenche l’événement Error
et affiche la page d’erreur appropriée. Il existe trois types de pages d’erreur : l’écran jaune de l’erreur d’exécution de la mort (YSOD) ; les détails de l’exception YSOD ; et pages d’erreur personnalisées. Dans le tutoriel précédent , nous avons configuré l’application pour utiliser une page d’erreur personnalisée pour les utilisateurs distants et le YSOD Détails de l’exception pour les utilisateurs qui visitent localement.
L’utilisation d’une page d’erreur personnalisée qui correspond à l’apparence du site est préférable à l’erreur d’exécution par défaut YSOD, mais l’affichage d’une page d’erreur personnalisée n’est qu’une partie d’une solution complète de gestion des erreurs. Lorsqu’une erreur se produit dans une application en production, il est important que les développeurs soient avertis de l’erreur afin qu’ils puissent découvrir la cause de l’exception et y remédier. En outre, les détails de l’erreur doivent être consignés afin que l’erreur puisse être examinée et diagnostiquée ultérieurement.
Ce tutoriel montre comment accéder aux détails d’une exception non gérée afin qu’elles puissent être journalisées et qu’un développeur soit averti. Les deux tutoriels suivants explorent les bibliothèques de journalisation des erreurs qui, après un peu de configuration, informent automatiquement les développeurs des erreurs d’exécution et consignent leurs détails.
Notes
Les informations examinées dans ce didacticiel sont les plus utiles si vous devez traiter des exceptions non gérées d’une manière unique ou personnalisée. Dans les cas où il vous suffit de consigner l’exception et d’avertir un développeur, l’utilisation d’une bibliothèque de journalisation des erreurs est la solution. Les deux didacticiels suivants fournissent une vue d’ensemble de deux bibliothèques de ce type.
Exécution de code lorsque l’événementError
est déclenché
Les événements fournissent à un objet un mécanisme permettant de signaler qu’un événement intéressant s’est produit et qu’un autre objet exécute du code en réponse. En tant que développeur ASP.NET, vous êtes habitué à penser en termes d’événements. Si vous souhaitez exécuter du code lorsque le visiteur clique sur un bouton particulier, vous créez un gestionnaire d’événements pour l’événement de Click
ce Bouton et y placez votre code. Étant donné que le runtime ASP.NET déclenche son Error
événement chaque fois qu’une exception non prise en charge se produit, il s’ensuit que le code pour la journalisation des détails de l’erreur va dans un gestionnaire d’événements. Mais comment créer un gestionnaire d’événements pour l’événement Error
?
L’événement Error
est l’un des nombreux événements de la HttpApplication
classe qui sont déclenchés à certaines étapes du pipeline HTTP pendant la durée de vie d’une requête. Par exemple, l’événement de BeginRequest
la HttpApplication
classe est déclenché au début de chaque requête ; son AuthenticateRequest
événement est déclenché lorsqu’un module de sécurité a identifié le demandeur. Ces HttpApplication
événements permettent au développeur de pages d’exécuter une logique personnalisée aux différents moments de la durée de vie d’une requête.
Les gestionnaires d’événements pour les HttpApplication
événements peuvent être placés dans un fichier spécial nommé Global.asax
. Pour créer ce fichier dans votre site web, ajoutez un nouvel élément à la racine de votre site web à l’aide du modèle Global Application Class portant le nom Global.asax
.
Figure 1 : Ajouter Global.asax
à votre application web
(Cliquez pour afficher l’image en taille réelle)
Le contenu et la Global.asax
structure du fichier créé par Visual Studio diffèrent légèrement selon que vous utilisez un projet d’application web (WAP) ou un projet de site web (WSP). Avec un WAP, le Global.asax
est implémenté sous la forme de deux fichiers distincts : Global.asax
et Global.asax.cs
. Le Global.asax
fichier ne contient qu’une @Application
directive qui fait référence au .cs
fichier ; les gestionnaires d’événements d’intérêt sont définis dans le Global.asax.cs
fichier. Pour les WSP, un seul fichier est créé, Global.asax
et les gestionnaires d’événements sont définis dans un <script runat="server">
bloc.
Le Global.asax
fichier créé dans un modèle wap de classe d’application globale de Visual Studio inclut des gestionnaires d’événements nommés Application_BeginRequest
, Application_AuthenticateRequest
et Application_Error
, qui sont des gestionnaires d’événements pour les HttpApplication
événements BeginRequest
, AuthenticateRequest
et Error
, respectivement. Il existe également des gestionnaires d’événements nommés Application_Start
, Session_Start
, Application_End
et Session_End
, qui sont des gestionnaires d’événements qui se déclenchent au démarrage de l’application web, au démarrage d’une nouvelle session, à la fin de l’application et à la fin d’une session, respectivement. Le Global.asax
fichier créé dans un WSP par Visual Studio contient uniquement les Application_Error
gestionnaires d’événements , Application_Start
, Session_Start
, Application_End
et Session_End
.
Notes
Lorsque vous déployez l’application ASP.NET, vous devez copier le fichier dans Global.asax
l’environnement de production. Le Global.asax.cs
fichier, qui est créé dans le WAP, n’a pas besoin d’être copié en production, car ce code est compilé dans l’assembly du projet.
Les gestionnaires d’événements créés par le modèle de classe d’application globale de Visual Studio ne sont pas exhaustifs. Vous pouvez ajouter un gestionnaire d’événements pour n’importe quel HttpApplication
événement en nommant le gestionnaire Application_EventName
d’événements . Par exemple, vous pouvez ajouter le code suivant au Global.asax
fichier pour créer un gestionnaire d’événements pour l’événementAuthorizeRequest
:
protected void Application_AuthorizeRequest(object sender, EventArgs e)
{
// Event handler code
}
De même, vous pouvez supprimer tous les gestionnaires d’événements créés par le modèle de classe d’application globale qui ne sont pas nécessaires. Pour ce tutoriel, nous avons uniquement besoin d’un gestionnaire d’événements pour l’événement Error
; n’hésitez pas à supprimer les autres gestionnaires d’événements du Global.asax
fichier.
Notes
Les modules HTTP offrent une autre façon de définir des gestionnaires d’événements pour HttpApplication
les événements. Les modules HTTP sont créés sous la forme d’un fichier de classe qui peut être placé directement dans le projet d’application web ou séparé dans une bibliothèque de classes distincte. Étant donné qu’ils peuvent être séparés dans une bibliothèque de classes, les modules HTTP offrent un modèle plus flexible et réutilisable pour la création HttpApplication
de gestionnaires d’événements. Alors que le Global.asax
fichier est spécifique à l’application web où il réside, les modules HTTP peuvent être compilés dans des assemblys, auquel cas l’ajout du module HTTP à un site web est aussi simple que de supprimer l’assembly dans le Bin
dossier et d’inscrire le module dans Web.config
. Ce didacticiel ne traite pas de la création et de l’utilisation de modules HTTP, mais les deux bibliothèques de journalisation des erreurs utilisées dans les deux didacticiels suivants sont implémentées en tant que modules HTTP. Pour plus d’informations sur les avantages des modules HTTP, consultez Utilisation de modules et de gestionnaires HTTP pour créer des composants de ASP.NET enfichables.
Récupération d’informations sur l’exception non gérée
À ce stade, nous avons un fichier Global.asax avec un gestionnaire d’événements Application_Error
. Lorsque ce gestionnaire d’événements s’exécute, nous devons informer un développeur de l’erreur et consigner ses détails. Pour accomplir ces tâches, nous devons d’abord déterminer les détails de l’exception qui a été levée. Utilisez la méthode de GetLastError
l’objet Server pour récupérer les détails de l’exception non gérée qui a provoqué le déclenchement de l’événementError
.
protected void Application_Error(object sender, EventArgs e)
{
// Get the error details
HttpException lastErrorWrapper =
Server.GetLastError() as HttpException;
}
La GetLastError
méthode retourne un objet de type Exception
, qui est le type de base pour toutes les exceptions dans le .NET Framework. Toutefois, dans le code ci-dessus, je transforme l’objet Exception retourné par GetLastError
dans un HttpException
objet. Si l’événement Error
est déclenché parce qu’une exception a été levée pendant le traitement d’une ressource ASP.NET, l’exception levée est encapsulée dans un HttpException
. Pour obtenir l’exception réelle qui a précipité l’événement Error, utilisez la InnerException
propriété . Si l’événement Error
a été déclenché en raison d’une exception basée sur HTTP, telle qu’une demande pour une page inexistante, un HttpException
est levé, mais il n’a pas d’exception interne.
Le code suivant utilise pour récupérer des GetLastErrormessage
informations sur l’exception qui a déclenché l’événement Error
, en stockant le HttpException
dans une variable nommée lastErrorWrapper
. Il stocke ensuite le type, le message et la trace de pile de l’exception d’origine dans trois variables de chaîne, en vérifiant si lastErrorWrapper
est l’exception réelle qui a déclenché l’événement Error
(dans le cas des exceptions basées sur HTTP) ou s’il s’agit simplement d’un wrapper pour une exception levée lors du traitement de la demande.
protected void Application_Error(object sender, EventArgs e)
{
// Get the error details
HttpException lastErrorWrapper =
Server.GetLastError() as HttpException;
Exception lastError = lastErrorWrapper;
if (lastErrorWrapper.InnerException != null)
lastError = lastErrorWrapper.InnerException;
string lastErrorTypeName = lastError.GetType().ToString();
string lastErrorMessage = lastError.Message;
string lastErrorStackTrace = lastError.StackTrace;
}
À ce stade, vous disposez de toutes les informations dont vous avez besoin pour écrire du code qui journalisera les détails de l’exception dans une table de base de données. Vous pouvez créer une table de base de données avec des colonnes pour chacun des détails d’erreur qui vous intéressent (type, message, trace de pile, etc.) ainsi que d’autres informations utiles, telles que l’URL de la page demandée et le nom de l’utilisateur actuellement connecté. Dans le Application_Error
gestionnaire d’événements, vous vous connectez ensuite à la base de données et insérez un enregistrement dans la table. De même, vous pouvez ajouter du code pour alerter un développeur de l’erreur par e-mail.
Les bibliothèques de journalisation des erreurs examinées dans les deux didacticiels suivants fournissent ces fonctionnalités prêtes à l’emploi. Il n’est donc pas nécessaire de générer cette journalisation et cette notification des erreurs vous-même. Toutefois, pour illustrer que l’événement Error
est déclenché et que le Application_Error
gestionnaire d’événements peut être utilisé pour consigner les détails de l’erreur et notifier un développeur, nous allons ajouter du code qui avertit un développeur lorsqu’une erreur se produit.
Notification d’un développeur lorsqu’une exception non prise en charge se produit
Lorsqu’une exception non prise en charge se produit dans l’environnement de production, il est important d’alerter l’équipe de développement afin qu’elle puisse évaluer l’erreur et déterminer les actions à entreprendre. Par exemple, en cas d’erreur lors de la connexion à la base de données, vous devrez doubler case activée votre chaîne de connexion et, peut-être, ouvrir un ticket de support auprès de votre société d’hébergement web. Si l’exception s’est produite en raison d’une erreur de programmation, il peut être nécessaire d’ajouter du code supplémentaire ou une logique de validation pour empêcher de telles erreurs à l’avenir.
Les classes .NET Framework de l’espace de noms facilitent l’envoiSystem.Net.Mail
d’un e-mail. La MailMessage
classe représente un message électronique et possède des propriétés telles que To
, From
, Subject
, Body
et Attachments
. SmtpClass
est utilisé pour envoyer un MailMessage
objet à l’aide d’un serveur SMTP spécifié ; les paramètres du serveur SMTP peuvent être spécifiés par programme ou de manière déclarative dans l’élément<system.net>
dans .Web.config file
Pour plus d’informations sur l’envoi de messages électroniques dans une application ASP.NET, case activée mon article Envoi de Email à partir d’un site pages Web ASP.NET et le FAQ System.Net.Mail.
Notes
L’élément <system.net>
contient les paramètres de serveur SMTP utilisés par la classe lors de l’envoi SmtpClient
d’un e-mail. Votre société d’hébergement web dispose probablement d’un serveur SMTP que vous pouvez utiliser pour envoyer des e-mails à partir de votre application. Consultez la section prise en charge de votre hôte web pour plus d’informations sur les paramètres du serveur SMTP que vous devez utiliser dans votre application web.
Ajoutez le code suivant au gestionnaire d’événements Application_Error
pour envoyer un e-mail à un développeur lorsqu’une erreur se produit :
void Application_Error(object sender, EventArgs e)
{
// Get the error details
HttpException lastErrorWrapper =
Server.GetLastError() as HttpException;
Exception lastError = lastErrorWrapper;
if (lastErrorWrapper.InnerException != null)
lastError = lastErrorWrapper.InnerException;
string lastErrorTypeName = lastError.GetType().ToString();
string lastErrorMessage = lastError.Message;
string lastErrorStackTrace = lastError.StackTrace;
const string ToAddress = "support@example.com";
const string FromAddress = "support@example.com";
const string Subject = "An Error Has Occurred!";
// Create the MailMessage object
MailMessage mm = new MailMessage(FromAddress, ToAddress);
mm.Subject = Subject;
mm.IsBodyHtml = true;
mm.Priority = MailPriority.High;
mm.Body = string.Format(@"
<html>
<body>
<h1>An Error Has Occurred!</h1>
<table cellpadding=""5"" cellspacing=""0"" border=""1"">
<tr>
<tdtext-align: right;font-weight: bold"">URL:</td>
<td>{0}</td>
</tr>
<tr>
<tdtext-align: right;font-weight: bold"">User:</td>
<td>{1}</td>
</tr>
<tr>
<tdtext-align: right;font-weight: bold"">Exception Type:</td>
<td>{2}</td>
</tr>
<tr>
<tdtext-align: right;font-weight: bold"">Message:</td>
<td>{3}</td>
</tr>
<tr>
<tdtext-align: right;font-weight: bold"">Stack Trace:</td>
<td>{4}</td>
</tr>
</table>
</body>
</html>",
Request.RawUrl,
User.Identity.Name,
lastErrorTypeName,
lastErrorMessage,
lastErrorStackTrace.Replace(Environment.NewLine, "<br />"));
// Attach the Yellow Screen of Death for this error
string YSODmarkup = lastErrorWrapper.GetHtmlErrorMessage();
if (!string.IsNullOrEmpty(YSODmarkup))
{
Attachment YSOD =
Attachment.CreateAttachmentFromString(YSODmarkup, "YSOD.htm");
mm.Attachments.Add(YSOD);
}
// Send the email
SmtpClient smtp = new SmtpClient();
smtp.Send(mm);
}
Bien que le code ci-dessus soit assez long, la majeure partie de celui-ci crée le code HTML qui apparaît dans l’e-mail envoyé au développeur. Le code commence par référencer le HttpException
retourné par la GetLastError
méthode (lastErrorWrapper
). L’exception réelle qui a été levée par la requête est récupérée via lastErrorWrapper.InnerException
et est affectée à la variable lastError
. Les informations de trace de type, de message et de pile sont récupérées à partir de lastError
et stockées dans trois variables de chaîne.
Ensuite, un MailMessage
objet nommé mm
est créé. Le corps de l’e-mail est au format HTML et affiche l’URL de la page demandée, le nom de l’utilisateur actuellement connecté et des informations sur l’exception (le type, le message et la trace de pile). L’une des choses intéressantes de la HttpException
classe est que vous pouvez générer le code HTML utilisé pour créer l’écran jaune des détails d’exception de la mort (YSOD) en appelant la méthode GetHtmlErrorMessage. Cette méthode est utilisée ici pour récupérer le balisage YSOD détails de l’exception et l’ajouter à l’e-mail en tant que pièce jointe. Un mot de mise en garde : si l’exception qui a déclenché l’événement Error
était une exception basée sur HTTP (par exemple, une demande pour une page inexistante), la GetHtmlErrorMessage
méthode retourne null
.
La dernière étape consiste à envoyer le MailMessage
. Pour ce faire, créez une méthode SmtpClient
et appelez sa Send
méthode.
Notes
Avant d’utiliser ce code dans votre application web, vous devez modifier les valeurs des ToAddress
constantes et FromAddress
de support@example.com à l’adresse e-mail à laquelle l’e-mail de notification d’erreur doit être envoyé et d’où provient. Vous devez également spécifier les paramètres du serveur SMTP dans la <system.net>
section de Web.config
. Consultez votre fournisseur d’hôte web pour déterminer les paramètres du serveur SMTP à utiliser.
Avec ce code en place chaque fois qu’une erreur se produit, le développeur reçoit un message électronique récapitulant l’erreur et incluant le YSOD. Dans le tutoriel précédent, nous avons démontré une erreur d’exécution en visitant Genre.aspx et en transmettant une valeur non valide ID
via la chaîne de requête, comme Genre.aspx?ID=foo
. La visite de la page avec le Global.asax
fichier en place génère la même expérience utilisateur que dans le tutoriel précédent. Dans l’environnement de développement, vous continuez à voir l’écran jaune des détails de l’exception de la mort, tandis que dans l’environnement de production, vous verrez la page d’erreur personnalisée. En plus de ce comportement existant, un e-mail est envoyé au développeur.
La figure 2 montre l’e-mail reçu lors de la visite de Genre.aspx?ID=foo
. Le corps de l’e-mail récapitule les informations d’exception, tandis que la YSOD.htm
pièce jointe affiche le contenu affiché dans le YSOD Détails de l’exception (voir figure 3).
Figure 2 : Le développeur reçoit une notification Email chaque fois qu’il existe une exception non prise en charge
(Cliquez pour afficher l’image en taille réelle)
Figure 3 : La notification Email inclut les détails de l’exception YSOD en tant que pièce jointe
(Cliquez pour afficher l’image en taille réelle)
Qu’en est-il de l’utilisation de la page d’erreur personnalisée ?
Ce tutoriel a montré comment utiliser Global.asax
et le gestionnaire d’événements pour exécuter du Application_Error
code lorsqu’une exception non prise en charge se produit. Plus précisément, nous avons utilisé ce gestionnaire d’événements pour informer un développeur d’une erreur ; nous pouvons l’étendre pour consigner également les détails de l’erreur dans une base de données. La présence du Application_Error
gestionnaire d’événements n’affecte pas l’expérience de l’utilisateur final. Ils voient toujours la page d’erreur configurée, qu’il s’agit des détails de l’erreur YSOD, de l’erreur d’exécution YSOD ou de la page d’erreur personnalisée.
Il est naturel de se demander si le fichier et Application_Error
l’événement Global.asax
sont nécessaires lors de l’utilisation d’une page d’erreur personnalisée. Lorsqu’une erreur se produit, la page d’erreur personnalisée s’affiche à l’utilisateur. Pourquoi ne pouvons-nous pas placer le code pour avertir le développeur et enregistrer les détails de l’erreur dans la classe code-behind de la page d’erreur personnalisée ? Bien que vous puissiez certainement ajouter du code à la classe code-behind de la page d’erreur personnalisée, vous n’avez pas accès aux détails de l’exception qui a déclenché l’événement lors de l’utilisation Error
de la technique que nous avons explorée dans le tutoriel précédent. L’appel de la GetLastError
méthode à partir de la page d’erreur personnalisée retourne Nothing
.
La raison de ce comportement est que la page d’erreur personnalisée est atteinte via une redirection. Lorsqu’une exception non gérée atteint le ASP.NET runtime, le moteur ASP.NET déclenche son Error
événement (qui exécute le Application_Error
gestionnaire d’événements), puis redirige l’utilisateur vers la page d’erreur personnalisée en émettant un Response.Redirect(customErrorPageUrl)
. La Response.Redirect
méthode envoie une réponse au client avec un code HTTP 302 status, en demandant au navigateur de demander une nouvelle URL, à savoir la page d’erreur personnalisée. Le navigateur demande alors automatiquement cette nouvelle page. Vous pouvez indiquer que la page d’erreur personnalisée a été demandée séparément de la page d’origine de l’erreur, car la barre d’adresse du navigateur change en URL de la page d’erreur personnalisée (voir figure 4).
Figure 4 : Lorsqu’une erreur se produit, le navigateur est redirigé vers l’URL de la page d’erreur personnalisée
(Cliquez pour afficher l’image en taille réelle)
L’effet net est que la requête dans laquelle l’exception non gérée s’est produite se termine lorsque le serveur répond avec la redirection HTTP 302. La requête suivante à la page d’erreur personnalisée est une toute nouvelle demande ; à ce stade, le moteur de ASP.NET a ignoré les informations d’erreur et, en outre, n’a aucun moyen d’associer l’exception non prise en charge de la demande précédente à la nouvelle demande pour la page d’erreur personnalisée. C’est pourquoi GetLastError
retourne null
lorsqu’elle est appelée à partir de la page d’erreur personnalisée.
Toutefois, il est possible que la page d’erreur personnalisée soit exécutée lors de la même demande qui a provoqué l’erreur. La Server.Transfer(url)
méthode transfère l’exécution à l’URL spécifiée et la traite dans la même requête. Vous pouvez déplacer le code du Application_Error
gestionnaire d’événements vers la classe code-behind de la page d’erreur personnalisée, en le remplaçant par Global.asax
le code suivant :
protected void Application_Error(object sender, EventArgs e)
{
// Transfer the user to the appropriate custom error page
HttpException lastErrorWrapper =
Server.GetLastError() as HttpException;
if (lastErrorWrapper.GetHttpCode() == 404)
{
Server.Transfer("~/ErrorPages/404.aspx");
}
else
{
Server.Transfer("~/ErrorPages/Oops.aspx");
}
}
À présent, lorsqu’une exception non gérée se produit, le Application_Error
gestionnaire d’événements transfère le contrôle vers la page d’erreur personnalisée appropriée en fonction du code http status. Étant donné que le contrôle a été transféré, la page d’erreur personnalisée a accès aux informations d’exception non gérées via Server.GetLastError
et peut informer un développeur de l’erreur et enregistrer ses détails. L’appel Server.Transfer
empêche le moteur ASP.NET de rediriger l’utilisateur vers la page d’erreur personnalisée. Au lieu de cela, le contenu de la page d’erreur personnalisée est retourné en tant que réponse à la page qui a généré l’erreur.
Résumé
Lorsqu’une exception non gérée se produit dans une application web ASP.NET, le runtime ASP.NET déclenche l’événement Error
et affiche la page d’erreur configurée. Nous pouvons informer le développeur de l’erreur, consigner ses détails ou la traiter d’une autre manière, en créant un gestionnaire d’événements pour l’événement Error. Il existe deux façons de créer un gestionnaire d’événements pour HttpApplication
des événements comme Error
: dans le Global.asax
fichier ou à partir d’un module HTTP. Ce tutoriel a montré comment créer un gestionnaire d’événements Error
dans le Global.asax
fichier qui avertit les développeurs d’une erreur au moyen d’un message électronique.
La création d’un gestionnaire d’événements Error
est utile si vous devez traiter des exceptions non gérées d’une manière unique ou personnalisée. Toutefois, la création de votre propre Error
gestionnaire d’événements pour journaliser l’exception ou avertir un développeur n’est pas l’utilisation la plus efficace de votre temps, car il existe déjà des bibliothèques de journalisation des erreurs gratuites et faciles à utiliser qui peuvent être configurées en quelques minutes. Les deux didacticiels suivants examinent deux bibliothèques de ce type.
Bonne programmation !
En savoir plus
Pour plus d’informations sur les sujets abordés dans ce tutoriel, reportez-vous aux ressources suivantes :
- Vue d’ensemble des modules HTTP et des gestionnaires HTTP ASP.NET
- Réponse appropriée aux exceptions non gérées - Traitement des exceptions non gérées
HttpApplication
Classe et l’objet application ASP.NET- Gestionnaires HTTP et modules HTTP dans ASP.NET
- Envoi de Email dans ASP.NET
- Présentation du
Global.asax
fichier - Utilisation de modules et de gestionnaires HTTP pour créer des composants ASP.NET enfichables
- Utilisation du fichier ASP.NET
Global.asax
- Utilisation des
HttpApplication
instances
Commentaires
https://aka.ms/ContentUserFeedback.
Bientôt disponible : Tout au long de 2024, nous allons supprimer progressivement GitHub Issues comme mécanisme de commentaires pour le contenu et le remplacer par un nouveau système de commentaires. Pour plus d’informations, consultezEnvoyer et afficher des commentaires pour