jeudi 21 octobre 2010

Argument de publication ou de rappel non valide

Lors d'un développement d'une application web avec AJAX, j'ai rempli un contrôle ListBox avec AJAX.
Il y a plusieurs appels AJAX sur la page avant Postback (que l’on clique sur le bouton pour enregistrement).
Au moment de l’enregistrement, j'ai eu le message d'erreur suivant:
Argument de publication ou de rappel non valide. La validation d'événement est activée via <pages enableEventValidation="true"/> dans la configuration ou via <%@ Page EnableEventValidation="true" %> dans une page. Pour des raisons de sécurité, cette fonctionnalité vérifie si les arguments des événements de publication ou de rappel proviennent du contrôle serveur qui les a rendus à l'origine. Si les données sont valides et attendues, utilisez la méthode ClientScriptManager.RegisterForEventValidation afin d'inscrire les données de publication ou de rappel pour la validation.
Depuis  ASP.NET 2.0 il y a une validation d'événement qui vérifie la requête POST pour s'assurer  que l'événement de Postback est valide.
La validation d'événement évite l'attaque qui renvoi  des données par l'événement qui ne vient pas d’un contrôle enregistré sur la page
Les solutions qui peuvent corriger le problème :
1. Désactiver la validation d'événement (mais risque de sécurité) avec EnableEventValidation = false.
2. Utiliser la méthode d’Ajax UpdatePanel (Placer le contrôle Listbox dans UpdatePanel et déclencher la mise à jour  pour ajouter/supprimer des éléments de Listbox). Le viewstate sera alors mis à jour et la validation d'événement passe.
3. Utiliser Postback pour ajouter/supprimer les items du contrôle ListBox
J'ai réussi à ne plus avoir ce message d'erreur en vidant le contenu du contrôle  ListBox  lors de l’envoi de formulaire. Le contrôle ListBox reste en même état avant et après Postback.
document.forms[0].onsubmit = function() {
    document.getElementById('IdControle').options.length = 0;
};

jeudi 7 octobre 2010

Ajax sur Firefox : La fonction onreadystatechange n'est pas appelée

Sur un projet dans lequel on a utilisé l’Ajax, on a rencontré un problème de code qui fonctionne bien sur Internet Explorer mais pas sur Firefox. Le problème réside dans la fonction définie par l’attribut "onreadystatechange" qui n'est jamais appelée sur Firefox.

Ci-dessous le déroulement d'appel Ajax que l'on a fait initialement:
-Instancier la classe XMLHttpRequest selon le navigateur.
-Définir la fonction qui doit être appelée dans l’attribut «onreadystatechange » (événement pour le changement d'état).
-Ouvrir la connexion avec la méthode « open »
-Envoyer la requête sur serveur de manière synchrone.
-Vérifier si l’état est prête/les données sont disponibles ou reçues (l'état défini par l'attribut « readyState » est égale à 4)
-Vérifier si le statut est égal à 200 = OK, 404 si non trouvé.
-Exécuter la fonction définie par « onreadystatechange »

var req;
function Initialize()
{
                try
                {
// Version récente d’Internet Explorer
                               req=new ActiveXObject("Msxml2.XMLHTTP");
                  }
                catch(e1)
 {
                               try
                                 {
// Version plus ancienne d’Internet Explorer
                                               req=new ActiveXObject("Microsoft.XMLHTTP");    }
                               catch(e2)
                               {
                                               req=null;
                               }
}
if(!req && typeof(XMLHttpRequest)!="undefined")
{
                               req=new XMLHttpRequest(); // Firefox, Safari,..
}
}

function Fonction1()
{
                Initialize();
if(req!=null)
{
                   /* 0= non initialisé,
                  si la connexion est déjà initialisée, on annule la requête HHTP
                  */
                  if (req.readyState != 0)
                        req.abort();
        
                 req.onreadystatechange = Fonction2;
                 /* mode : POST/GET,
    url : url où trouver les données,
    type : true(asynchrone), false(synchrone)
 */
                 req.open(mode,url, type);
                 req.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
                var data = "AJAX_QUERY= TestAjaxQuery" ;
                req.send(data);
}
}

function Fonction2()
{
                if (req.readyState == 4)
                {
                                if (req.status == 200) // OK
                                {
                                               Alert('Retour Ajax OK');
                               }
                }
}

La fonction « Fonction2 » n’est jamais exécutée sur Firefox. Après les recherches, j’ai découvert que cette anomalie est reproductible pour l’appel synchrone sur Firefox et il s'agit d'un bug.
https://bugzilla.mozilla.org/show_bug.cgi?id=412112
Sur un appel synchrone, Firefox considère que la réponse d'Ajax est déjà arrivée et qu'il n'est pas nécessaire de vérifier l'état. Par conséquence, il n’est pas nécessaire de vérifier le changement d’état.

Le code devient alors comme suit:


function Fonction1()
{
         Initialize();
        if(req!=null)
        {
           /*0= non initialisé
            si la connexion est déjà initialisée, on annule la requête HHTP
          */
              if (req.readyState != 0)
                   req.abort();

             /* mode : POST/GET,
 url : url où trouver les données,
type : true(asynchrone), false(synchrone)
*/
             req.open(mode,url, type);
             req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
             var data = "AJAX_QUERY= TestAjaxQuery";
             req.send(data);
            //req.onreadystatechange = Fonction2
           if (req.status == 200) // OK
           {
            Fonction2();
           }
       }
}

function Fonction2()
{
     Alert('Retour Ajax OK');
}

Cette fois ci le code fonctionne sur Internet Explorer et sur Firefox.

Pour voir plus loin:
http://www.onejohn.org/wpjohn/2008/05/firefox-bug-with-onreadystatechange/
http://lukav.com/wordpress/2007/04/12/firefox-firebug-and-synchronos-calls-problem/