4760 votes

Comment passer "Null" (un vrai nom de famille !) à un service web SOAP en ActionScript 3

Nous avons un employé dont le nom de famille est Null. Notre application de recherche d'employés est tuée lorsque ce nom de famille est utilisé comme terme de recherche (ce qui arrive assez souvent maintenant). L'erreur reçue (merci Fiddler !) est la suivante :

<soapenv:Fault>
   <faultcode>soapenv:Server.userException</faultcode>
   <faultstring>coldfusion.xml.rpc.CFCInvocationException: [coldfusion.runtime.MissingArgumentException : The SEARCHSTRING parameter to the getFacultyNames function is required but was not passed in.]</faultstring>

Mignon, hein ?

Le type de paramètre est string .

J'utilise :

  • WSDL ( SOAP )
  • Flex 3.5
  • ActionScript 3
  • ColdFusion 8

Notez que l'erreur n'est pas se produisent lorsque l'on appelle le webservice en tant qu'objet à partir d'une page ColdFusion.

6 votes

Cela ne vous aidera peut-être pas beaucoup à résoudre votre problème spécifique, mais SOAP 1.2 autorise les valeurs nulles, cf. w3.org/TR/2001/WD-soap12-20010709/#_Toc478383513

8 votes

J'ai le sentiment que ça implique Dave Null.

2 votes

Au moins, ça n'implique pas Chuck Norris. Voici pourquoi il faut rester loin de lui en code : codesqueeze.com/

1153voto

Ben Burns Points 4058

La traque

Au début, je pensais que c'était un bug de coercition où null a été contraint de "null" et un test de "null" == null passait. Ce n'est pas le cas. J'étais proche, mais j'avais vraiment, vraiment tort. Désolé pour ça !

Depuis, j'ai fait beaucoup de bricolage sur wonderfl.net et de retracer le code dans mx.rpc.xml.* . À la ligne 1795 de XMLEncoder (dans la source 3.5), en setValue tout le codage XMLEn se résume à

currentChild.appendChild(xmlSpecialCharsFilter(Object(value)));

ce qui est essentiellement la même chose que :

currentChild.appendChild("null");

Ce code, selon mon bidouillage original, renvoie un élément XML vide. Mais pourquoi ?

Cause

Selon le commentateur Justin Mclean sur le rapport de bug FLEX-33664 Si l'on ne parvient pas à trouver le coupable (voir les deux derniers tests dans mon test d'essai), ce qui suit est la cause du problème. violon qui le vérifient) :

var thisIsNotNull:XML = <root>null</root>;
if(thisIsNotNull == null){
    // always branches here, as (thisIsNotNull == null) strangely returns true
    // despite the fact that thisIsNotNull is a valid instance of type XML
}

Lorsque currentChild.appendChild reçoit la chaîne de caractères "null" il le convertit d'abord en un élément XML racine avec du texte. null et teste ensuite cet élément par rapport au littéral nul. Il s'agit d'un test d'égalité faible, donc soit le XML contenant null est converti en type null, soit le type null est converti en un élément xml Root contenant la chaîne "null", et le test passe alors qu'il devrait échouer. Une solution pourrait être de toujours utiliser égalité stricte lors de la vérification de la "nullité" du XML (ou de tout autre document, en fait).

Solution

La seule solution raisonnable à laquelle je peux penser, à moins de corriger ce bogue dans toutes les versions d'ActionScript, est de tester les champs pour "null" et "null". les échapper comme Valeurs CDATA .

Les valeurs CDATA sont le moyen le plus approprié de muter une valeur textuelle entière qui, autrement, poserait des problèmes d'encodage/décodage. Le codage hexadécimal, par exemple, est destiné aux caractères individuels. Les valeurs CDATA sont préférables lorsque vous échappez l'intégralité du texte d'un élément. La principale raison en est qu'elles préservent la lisibilité humaine.

302voto

Alex Dupuy Points 2253

Sur le note de xkcd le Site web de Bobby Tables donne de bons conseils pour éviter l'interprétation incorrecte des données de l'utilisateur (dans ce cas, la chaîne "Null") dans les requêtes SQL dans divers langages, dont les suivants ColdFusion .

La question n'indique pas clairement qu'il s'agit de la source du problème, et étant donné la solution notée dans un commentaire de la première réponse (intégration des paramètres dans une structure), il semble probable qu'il s'agisse d'autre chose.

245voto

doc_180 Points 8017

Le problème pourrait provenir de l'encodeur SOAP de Flex. Essayez d'étendre l'encodeur SOAP dans votre application Flex et déboguez le programme pour voir comment la valeur nulle est traitée.

A mon avis, c'est passé comme NaN (Pas un numéro). Cela peut parfois perturber le processus de désarchivage des messages SOAP (notamment dans le cadre de l'initiative JBoss 5 serveur...). Je me souviens d'avoir étendu l'encodeur SOAP et d'avoir effectué une vérification explicite de la façon dont NaN est traité.

12 votes

Name="Null" est bien sûr utile, et je ne vois pas comment il devrait être lié à NaN.

130voto

JeffryHouser Points 35567

@doc_180 avait le bon concept, sauf qu'il se concentre sur les chiffres, alors que l'affiche originale avait des problèmes avec les chaînes de caractères.

La solution consiste à modifier le mx.rpc.xml.XMLEncoder fichier. Il s'agit de la ligne 121 :

    if (content != null)
        result += content;

(J'ai consulté le kit SDK Flex 4.5.1 ; les numéros de ligne peuvent différer dans d'autres versions).

En fait, la validation échoue parce que le "contenu est nul" et que votre argument n'est pas ajouté au paquet SOAP sortant, ce qui provoque l'erreur de paramètre manquant.

Vous devez étendre cette classe pour supprimer la validation. Ensuite, il y a une grande boule de neige dans la chaîne, en modifiant SOAPEncoder pour utiliser votre XMLEncoder modifié, puis en modifiant Operation pour utiliser votre SOAPEncoder modifié, puis en modifiant WebService pour utiliser votre classe Operation alternative.

J'ai passé quelques heures dessus, mais je dois passer à autre chose. Ça va probablement prendre un jour ou deux.

Vous pouvez peut-être corriger la ligne XMLEncoder et faire un peu de singe Parcheando pour utiliser votre propre classe.

J'ajouterai également que si vous passez à l'utilisation de RemoteObject/AMF avec ColdFusion, le null est transmis sans problème.


Mise à jour du 16/11/2013 :

J'ai encore un ajout récent à mon dernier commentaire sur RemoteObject/AMF. Si vous utilisez ColdFusion 10, les propriétés dont la valeur est nulle sur un objet sont supprimées de l'objet côté serveur. Ainsi, vous devez vérifier l'existence des propriétés avant d'y accéder ou vous obtiendrez une erreur d'exécution.

Vérifiez comme ceci :

<cfif (structKeyExists(arguments.myObject,'propertyName')>
 <!--- no property code --->
<cfelse>
 <!--- handle property  normally --->
</cfif>

Il s'agit d'un changement de comportement par rapport à ColdFusion 9, où les propriétés nulles se transformaient en chaînes vides.


Edit 12/6/2013

Étant donné qu'une question a été posée sur la façon dont les valeurs nulles sont traitées, voici un exemple d'application rapide pour montrer comment une chaîne de caractères "null" est liée au mot réservé null.

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
               xmlns:s="library://ns.adobe.com/flex/spark"
               xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" initialize="application1_initializeHandler(event)">
    <fx:Script>
        <![CDATA[
            import mx.events.FlexEvent;

            protected function application1_initializeHandler(event:FlexEvent):void
            {
                var s :String = "null";
                if(s != null){
                    trace('null string is not equal to null reserved word using the != condition');
                } else {
                    trace('null string is equal to null reserved word using the != condition');
                }

                if(s == null){
                    trace('null string is equal to null reserved word using the == condition');
                } else {
                    trace('null string is not equal to null reserved word using the == condition');
                }

                if(s === null){
                    trace('null string is equal to null reserved word using the === condition');
                } else {
                    trace('null string is not equal to null reserved word using the === condition');
                }
            }
        ]]>
    </fx:Script>
    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>
</s:Application>

La sortie de la trace est :

La chaîne de caractères nulle n'est pas égale au mot réservé nul en utilisant la condition !=.

La chaîne de caractères nulle n'est pas égale au mot réservé nul en utilisant la condition ==.

la chaîne de caractères nulle n'est pas égale au mot réservé nul en utilisant la condition ===

10 votes

@Reboog711 Le nom de famille de l'employé est littéralement la chaîne "Null", comme dans "Mon nom est Pat Null". Votre réponse ne transmet pas le nom de famille de l'employé. Votre réponse ne fait que cacher le fait que "Null" est contraint de manière inappropriée au concept de null dans le langage par la méthode appendChild() décrite par Ben Burns. Le résultat est toujours l'incapacité du système à traiter M. ou Mme Null.

2 votes

@MaxxDaymon Je pense que vous interprétez mal ma réponse. Elle ne présente pas une solution, mais plutôt une explication de la raison pour laquelle le problème se produit, et cite le code pertinent du cadre Flex. Mon édition la plus récente est peut-être mal placée, car elle traite d'une autre approche et n'est pas directement liée à la question initiale.

1 votes

Tu es en quelque sorte sur la bonne voie, mais à ce stade du code. content est la chaîne de caractères "null" et "null" == null renvoie false, donc ce test se comporte comme prévu. Je pense plutôt que le problème est un mélange de la façon dont XML.appendChild traite un argument de type chaîne de caractères et de la façon dont un élément XML Root contenant uniquement la chaîne de caractères "null" peut être converti en un élément littéral. null .

65voto

doogle Points 2148

Traduire tous les caractères en leurs équivalents hexa. Dans ce cas, Null serait converti en &#4E;&#75;&#6C;&#6C;

43 votes

S'il vous plaît, ne faites pas ça. CDATA a été créé pour être utilisé dans les cas où vous devez échapper un bloc entier de texte.

4 votes

Je peux me tromper, mais je ne pense pas qu'un vote négatif juste parce que ce n'était pas votre c'est comme ça que c'est censé fonctionner. Il faut aussi garder à l'esprit que le problème appelle une solution heuristique puisqu'il n'y a pas une seule façon évidente, comme le montre la variété des solutions postées. Enfin, tout en gardant à l'esprit que je ne connais pas la CF, un décodeur n'assimilerait-il pas simplement le texte interne de <message>< ![CDATA[NULL]]></message> au texte interne de <message>NULL</message> ? Si c'est le cas, alors CDATA est-il vraiment une solution ?

7 votes

J'ai rétrogradé parce que c'est un anti-modèle. Dans ce cas, le bug n'est pas dans CF, mais dans ActionScript. Mais vous soulevez néanmoins un bon point. Je vais ajouter un test à mon bidule pour l'encodage des CDATA.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X