none
Message d'erreur compréhensible aux utilisateurs c# RRS feed

  • Question

  • Bonjour,
    j'ai de temps en temps, j'ai le message d'erreur suivant :

    • Server was unable to process request. ---> Original error message: Database problem while fetch entity failed. ---> [IBM U2][UODOTNET - UNICLIENT][ErrorCode=45002] Cannot perform operation on a null recordID

    Comment peux-je afficher un autre message plus compréhensible aux utilisateurs ?

    Par exemple :

    • Il ne faut pas trop longtemps attendre avant de valider ce formulaire  : votre session a expiré

    au lieu d'afficher le message ci-dessous ?

    Bonne journée

    mercredi 28 novembre 2012 20:17

Réponses

  • Attention try/catch est un bloc d'instructions donc il faut le placer dans votre code (et non dans votre classe) en englobant la partie qui peut provoquer l'erreur afin que le catch intercepte cette erreur.

    Si je comprends bien votre contexte plutôt que de relancer une exception il faut afficher le message dans 'ErrorLabel' :

    protected void post_Click(object sender, System.EventArgs e)
            {
                ErrorLabel.Visible = false;
                if (IsValid() && Page.IsValid)
                {
                    try{
                      // On protège l'exécution de ce code, si une erreur arrive dans ce bloc on
                      // se rendra dans le bloc catch
                      
                      ScriptManager.RegisterStartupScript(this, this.GetType(), "Page", "post()", true); //appel function post()
                      SetPageState();
                      Session["EntreeNouveau"] = "NouveauFormEntre";
                      Response.Redirect("confirmer.aspx");
                    }catch(Exception ex){
                      if(ex.ErroCode == 45002) 
                      {
                          ErrorLabel.Text = "Il ne faut pas trop attendre...";
                      }else
                      {
                          ErrorLabel.Text = ex.Message;
                      }                  
                      ErrorLabel.Visible = true;
                    }
                }
            }
            

    Si vous n'êtes pas familier avec les exceptions et le try/catch je vous conseille de consulter la MSDN :

    http://msdn.microsoft.com/fr-fr/library/ms173160(v=vs.80).aspx

    sur le fonctionnement des exceptions et pour la référence aux instructions try/catch/finally.

    Cordialement,

    Yan Grenier

    jeudi 29 novembre 2012 16:16
  • Yan et moi t'avons répondu sur la gestion des exceptions... le dernier message de Yan est prendre aussi en considération.

    A la lecture de ton message, j'ai l'impression que ton besoin est plus général que simplement gérer des exceptions... il semble s'agir de gérer la fin de session de l'utilisateur.

    Si c'est le cas, il faut prendre un peu de recul pour mettre en place un système plus global. En effet,  il te faudrait gérer ce cas dans tout tes événements utilisateurs, ce qui n'est pas jouable.

    J'ai trouvé quelques articles sur ce sujet qui te donneront des infos intéressantes... à toi de voir comment tu veux implémenter tout ça :

    • http://aspalliance.com/520_Detecting_ASPNET_Session_Timeouts.all
    • http://www.codeproject.com/Articles/15575/Detecting-Session-Timeout-and-Redirect-to-HomePage
    • http://www.eggheadcafe.com/tutorials/asp-net/7262426f-3c65-4c90-b49c-106470f1d22a/build-an-aspnet-session-timeout-redirect-control.aspx
    • Proposé comme réponse Hervé DORIER jeudi 29 novembre 2012 16:54
    • Marqué comme réponse Aurel Bera mardi 4 décembre 2012 08:26
    jeudi 29 novembre 2012 16:54
  • Bonjour,

    Votre Exception provient d'un accès en base SQL donc il faut utiliser SqlException. A partir de cette classe d'exception, vous aurez le code d'exception. N'utilisez jamais une reconnaissance d'erreur par le message car si celui-ci est dans une autre langue, l'application ne traitera jamais votre code. Il faut impérativement utiliser ErrorCode.

    La classe Exception est la haute hiérarchiquement et répond à une erreur tout genre (générique).

    Est-ce que cela vous aides ?

     

    Cordialement


    Merci de valider par "Proposer comme réponse" si celle-ci répond à votre demande !

    • Marqué comme réponse Aurel Bera mardi 11 décembre 2012 08:28
    vendredi 30 novembre 2012 14:41

Toutes les réponses

  • Bonjour,

    A moins de ne pas avoir tout saisi il suffit d'intercepter ce message d'erreur et lever une autre exception plus compréhensible genre :

    try{
     ...
    }catch(Exception ex){
     if(ex.Message.Contains("Cannot perform operation on a null recordID"){
      throw new ApplicationException("Il ne faut pas trop attendre...");
     }else{
      throw ex;
     }
    }

    Bien sur à modifier en fonction du type d'exception si elle est particulière, où si le code erreur est accessible pour isoler les différents cas à intercepter.

    Après si le fait de relancer une exception n'est pas compatible avec votre code il faut corriger en fonction de vos méthodes d'affichage des erreurs, mais le principe reste le même.

    Cordialement,

    Yan Grenier

    jeudi 29 novembre 2012 07:46
  • Bonjour,

    Pour ma part j'éviterais

    if(ex.Message.Contains("Cannot perform operation on a null recordID"){

    Si c'est possible, il vaut mieux :

    1. Faire un try/catch sur la classe de l'exception à gérer, du style
    }catch(SqlException ex){

      2. Tester sur le code erreur 45002

    try{
     ...
    }catch(Exception ex){
     if(ex.ErroCode == 45002) {
      throw new ApplicationException("Il ne faut pas trop attendre...", ex);
     }else{
      throw;
     }
    }

    Pour aller plus loin dans la gestion des Exceptions, je conseillerais de : 

    - Créer un constructeur ApplicationException permettant d'initialiser l'innerException avec l'exception d'origine. Cela permet de conserver la stacktrace dans les logs.

    - D'éviter les "else throw ex" au profit d'un "else throw"... toujours pour une meilleure gestion de la stacktrace.

    Pas contre, bien vu l'utilisation d'une classe d'exception custom "ApplicationException" qui permet de voir dans le code appelant que l'exception a déjà été gérée.

    Cordialement.


    • Proposé comme réponse Hervé DORIER jeudi 29 novembre 2012 13:48
    jeudi 29 novembre 2012 13:48
  • Bonjour,

    Pour ma part j'éviterais

    if(ex.Message.Contains("Cannot perform operation on a null recordID"){

    Si c'est possible, il vaut mieux :

    1. Faire un try/catch sur la classe de l'exception à gérer, du style
    }catch(SqlException ex){

      2. Tester sur le code erreur 45002

    try{
     ...
    }catch(Exception ex){
     if(ex.ErroCode == 45002) {
      throw new ApplicationException("Il ne faut pas trop attendre...", ex);
     }else{
      throw;
     }
    }

    Oui c'est exact c'est pour cela que j'ai précisé "Bien sur à modifier en fonction du type d'exception si elle est particulière, où si le code erreur est accessible pour isoler les différents cas à intercepter".

    Tout dépend du cas, je connais des libs qui ne fournissent aucune informations susceptible d'aider à la décision, donc il ne reste que l'analyse du texte du message (sympathique quand c'est localisé :) ).

    C'est vrai que je n'ai pas spécifié le innerException comme apparemment la demande résidait essentiellement sur un changement du message d'erreur pour l'utilisateur final.

    Concernant le "throw" au lieu du "throw ex" je croyais que c'était parfaitement identique : il y a une différence ?

    Concernant l'utilisation d'ApplicationException c'est essentiellement une recommandation de ne pas utiliser "Exception" directement que je vois un peu partout dans les bonnes pratiques de développement où l'analyse de code.

    Cordialement,

    Yan Grenier

    jeudi 29 novembre 2012 14:00
  • Bonjour Yan et Hervé,

    Merci vos réponses...

    Est-ce qu'il faut que je mette ce catch/try à l'endroit du bouton ?

     protected void post_Click(object sender, System.EventArgs e)
            {
                ErrorLabel.Visible = false;
                if (IsValid() && Page.IsValid)
                {
                    ScriptManager.RegisterStartupScript(this, this.GetType(), "Page", "post()", true); //appel function post()
                    SetPageState();
                    Session["EntreeNouveau"] = "NouveauFormEntre";
                    Response.Redirect("confirmer.aspx");
                }
    
            } 

    ou bien, comme vous dites :

    public partial class nouveau_utilisateur_inscriptionCodeProm : System.Web.UI.Page
    {
    	try{
    		//... etc
    		protected void Page_Load(object sender, System.EventArgs e)
    			{
    			//... etc
    			}
    			
    		private void InitializeComponent()
    			{
    				//... etc
    			}
    
    		private void LoadPageState()
    			{
    			//... etc
    			}
    		//... etc
    		
    		}
    		catch(Exception ex)
    		{
    		 if(ex.ErroCode == 45002) 
    			 {
    			  throw new ApplicationException("Il ne faut pas trop attendre...", ex);
    			 }else
    			 {
    			  throw;
    			 }
    		}
    
    	
    }
    
    

    Bonne journée

    Cordialement

    jeudi 29 novembre 2012 15:32
  • Attention try/catch est un bloc d'instructions donc il faut le placer dans votre code (et non dans votre classe) en englobant la partie qui peut provoquer l'erreur afin que le catch intercepte cette erreur.

    Si je comprends bien votre contexte plutôt que de relancer une exception il faut afficher le message dans 'ErrorLabel' :

    protected void post_Click(object sender, System.EventArgs e)
            {
                ErrorLabel.Visible = false;
                if (IsValid() && Page.IsValid)
                {
                    try{
                      // On protège l'exécution de ce code, si une erreur arrive dans ce bloc on
                      // se rendra dans le bloc catch
                      
                      ScriptManager.RegisterStartupScript(this, this.GetType(), "Page", "post()", true); //appel function post()
                      SetPageState();
                      Session["EntreeNouveau"] = "NouveauFormEntre";
                      Response.Redirect("confirmer.aspx");
                    }catch(Exception ex){
                      if(ex.ErroCode == 45002) 
                      {
                          ErrorLabel.Text = "Il ne faut pas trop attendre...";
                      }else
                      {
                          ErrorLabel.Text = ex.Message;
                      }                  
                      ErrorLabel.Visible = true;
                    }
                }
            }
            

    Si vous n'êtes pas familier avec les exceptions et le try/catch je vous conseille de consulter la MSDN :

    http://msdn.microsoft.com/fr-fr/library/ms173160(v=vs.80).aspx

    sur le fonctionnement des exceptions et pour la référence aux instructions try/catch/finally.

    Cordialement,

    Yan Grenier

    jeudi 29 novembre 2012 16:16
  • Merci Yan
    c'est très apprécié...

    avec

    if (ex.ErrorCode == 45002)

    j'ai un message d'erreur

     'System.Exception' ne contient pas une définition pour 'ErrorCode' et aucune méthode d'extension 'ErrorCode' acceptant un premier argument de type 'System.Exception' n'a été trouvée (une directive using ou une référence d'assembly est-elle manquante ?)

    C’est pourquoi? Vous avez une idée...

    Merci

    Cordialement

    jeudi 29 novembre 2012 16:38
  • Oui, il y a une différence notable, et importante si tu souhaite gérer ton exception sur plusieurs niveaux.

    //Cas 1
    try{
     ...
    }catch(Exception ex){
      throw ex; // L'exception ex est remontée à l'appelant, mais la stack est perdue.
    }
    
    //Cas 2
    try{
     ...
    }catch(Exception ex){
      throw; // L'exception ex est remontée à l'appelant en conservant la stack.
    }

    Dans le second cas, si tu affiche la stack trace dans la page HTML, tu verras toute la pile de l'exception.

    Dans le premier cas, tu n'auras que la pile à partir de la méthode qui a envoyé le "throw ex".

    jeudi 29 novembre 2012 16:42
  • Ha merci beaucoup, je ne savais pas cela.

    Je me coucherais mon bête :)

    Cordialement,

    Yan Grenier

    jeudi 29 novembre 2012 16:45
  • Yan et moi t'avons répondu sur la gestion des exceptions... le dernier message de Yan est prendre aussi en considération.

    A la lecture de ton message, j'ai l'impression que ton besoin est plus général que simplement gérer des exceptions... il semble s'agir de gérer la fin de session de l'utilisateur.

    Si c'est le cas, il faut prendre un peu de recul pour mettre en place un système plus global. En effet,  il te faudrait gérer ce cas dans tout tes événements utilisateurs, ce qui n'est pas jouable.

    J'ai trouvé quelques articles sur ce sujet qui te donneront des infos intéressantes... à toi de voir comment tu veux implémenter tout ça :

    • http://aspalliance.com/520_Detecting_ASPNET_Session_Timeouts.all
    • http://www.codeproject.com/Articles/15575/Detecting-Session-Timeout-and-Redirect-to-HomePage
    • http://www.eggheadcafe.com/tutorials/asp-net/7262426f-3c65-4c90-b49c-106470f1d22a/build-an-aspnet-session-timeout-redirect-control.aspx
    • Proposé comme réponse Hervé DORIER jeudi 29 novembre 2012 16:54
    • Marqué comme réponse Aurel Bera mardi 4 décembre 2012 08:26
    jeudi 29 novembre 2012 16:54
  • Bonjour Yan et Hervé,
    Merci pour toutes ces explications.

    À propos de message d'erreur, faut-il préparer un gestionnaire dans laquelle il faut mettre mon erreur dans la liste?
    Comment, je peux trouver la liste des gestionnaires actifs sur mon pc?

    System.Exception' ne contient pas une définition pour 'ErrorCode' et aucune méthode d'extension 'ErrorCode' acceptant un premier argument de type 'System.Exception' n'a été trouvée (une directive using ou une référence d'assembly est-elle manquante ?)

    En outre, pour le moment, j'ai personnalisé le message d'erreur avec mon web.config suite l'article suivant...

    http://www.codeproject.com/Articles/2345/Custom-Errors-in-ASP-NET

    Mais c'est pour tous les messages donc ce n'est pas bon... C'est bon pour le timeout, mais s'il y a d'autres erreurs... Par exemple le serveur mail ou serveur MySql tombe...
    Du coup il ne faut pas afficher toujours le même message...

    C'est pour quoi, les mots clés try et catch est plus souple et plus adaptable selon l'erreur de l'utilisateur... Et surtout, si l'erreur ne vient pas de l'utilisateur...

    Je suis en train de lire tous vos liens
    Merci encore

    Cordialement

    jeudi 29 novembre 2012 17:12
  • L'option de la page d'erreur est très bonne aussi.

    Je t'invite à lire cette page qui explique la gestion des exceptions dans les applications asp.net et comment mettre en place une page d'erreur dans laquelle tu vas pouvoir faire des traitements spécifiques en fonction de l'exception qui a été générée.

    jeudi 29 novembre 2012 18:27
  • Bonjour,

    Votre Exception provient d'un accès en base SQL donc il faut utiliser SqlException. A partir de cette classe d'exception, vous aurez le code d'exception. N'utilisez jamais une reconnaissance d'erreur par le message car si celui-ci est dans une autre langue, l'application ne traitera jamais votre code. Il faut impérativement utiliser ErrorCode.

    La classe Exception est la haute hiérarchiquement et répond à une erreur tout genre (générique).

    Est-ce que cela vous aides ?

     

    Cordialement


    Merci de valider par "Proposer comme réponse" si celle-ci répond à votre demande !

    • Marqué comme réponse Aurel Bera mardi 11 décembre 2012 08:28
    vendredi 30 novembre 2012 14:41
  • Bonjour,

    Est-ce que vous avez testé les solutions proposées ? Merci de partager avec nous les résultats, afin que d'autres personnes avec le même problème puissent profiter de cette solution.

    Cordialement,

    Aurel


    Aurel BERA, Microsoft
    Microsoft propose ce service gratuitement, dans le but d'aider les utilisateurs et d'élargir les connaissances générales liées aux produits et technologies Microsoft. Ce contenu est fourni "tel quel" et il n'implique aucune responsabilité de la part de Microsoft.

    lundi 3 décembre 2012 07:58
  • Bonjour,

    Pouvons-nous considérer que vous avez résolu votre problème avec les scénarios proposés ? Dans l'affirmative, pourriez-vous partager avec nous la solution, afin que d'autres personnes avec le même problème puissent profiter de cette solution ?

    Désormais, nous marquons les solutions proposées. N'hésitez pas à revenir et supprimer la réponse marquée si la solution n’est pas correcte. Merci !

    Cordialement,

    Aurel


    Aurel BERA, Microsoft
    Microsoft propose ce service gratuitement, dans le but d'aider les utilisateurs et d'élargir les connaissances générales liées aux produits et technologies Microsoft. Ce contenu est fourni "tel quel" et il n'implique aucune responsabilité de la part de Microsoft.

    mardi 4 décembre 2012 08:26
  • Bonjour,

    J’étais malade... d'où vient de mon silence...

    J'imagine que la réponse de Lyamine est plus adaptée dans mon cas... Je vais voir comment je peux la réaliser et je vais vous donner la suite...

    Merci
    lundi 10 décembre 2012 16:46