Pytanie Jak przekazać "Null" (prawdziwe nazwisko!) Do usługi sieciowej SOAP w ActionScript 3?


Mamy pracownika o nazwisku Null. Nasza aplikacja do wyszukiwania pracowników jest zabijana, gdy to nazwisko jest używane jako wyszukiwane hasło (co zdarza się dość często teraz). Otrzymany błąd (dzięki Fiddler!) To:

<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>

Słodkie, co?

Typ parametru to string.

Ja używam:

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

Zauważ, że błąd nie występuje podczas wywoływania usługi internetowej jako obiektu ze strony ColdFusion.


4475
2017-12-16 00:42


pochodzenie


To może nie pomóc Ci w tym konkretnym problemie, ale SOAP 1.2 pozwala na wartości zerowe, zobacz w3.org/TR/2001/WD-soap12-20010709/#_Toc478383513 - JensG
Mam przeczucie, że dotyczy to Dave'a Null'a. - George Gibson
Przynajmniej nie dotyczy to Chucka Norrisa. Oto dlaczego trzymać się z dala od niego w kodzie: codesqueeze.com/... - SDsolar
Czy pracownik rozważał zmianę nazwiska? - Tatranskymedved
Przywoływany w BBC: bbc.com/future/story/... - biziclop


Odpowiedzi:


 Śledzenie go

Na początku myślałem, że to błąd z przymusu null został zmuszony do "null" i test "null" == null przechodził. To nie jest. Byłem blisko, ale bardzo, bardzo źle. Przepraszam za to!

Od tego czasu dużo zrobiłem bawi się na wonderfl.net i śledzenie kodu w mx.rpc.xml.*. W linii 1795 z XMLEncoder (w źródle 3.5), w setValue, całe XMLEncoding sprowadza się do

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

który jest zasadniczo taki sam jak:

currentChild.appendChild("null");

Ten kod, zgodnie z moim oryginalnym skrzypce, zwraca pusty element XML. Ale dlaczego?

 Przyczyna

Według komentatora Justina Mcleana w sprawie zgłoszenia błędu FLEX-33664, to jest winowajca (zobacz ostatnie dwa testy w moim skrzypce które to potwierdzają):

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
}

Gdy currentChild.appendChild jest przekazywany ciąg znaków "null", najpierw konwertuje go do głównego elementu XML z tekstem null, a następnie testuje ten element przed literałem null. Jest to słaby test równości, więc albo plik XML zawierający wartość null jest wymuszany na typ zerowy, albo typ zerowy jest wymuszany na źródłowym elemencie xml zawierającym ciąg "null", a test przechodzi tam, gdzie prawdopodobnie mógł się nie powieść. Jedna poprawka może być zawsze używana ścisła równość testy podczas sprawdzania XML (lub cokolwiek, naprawdę) dla "zerowej".

Rozwiązanie

Jedynym rozsądnym rozwiązaniem, które może mi pomóc, poza naprawianiem tego błędu w każdej cholernej wersji ActionScript, jest testowanie pól "null" i uciec im jako Wartości CDATA. 

Wartości CDATA są najbardziej odpowiednim sposobem na zmutowanie całej wartości tekstu, która w przeciwnym razie spowodowałaby problemy z kodowaniem / dekodowaniem. Kodowanie szesnastkowe jest na przykład przeznaczone dla pojedynczych znaków. Wartości CDATA są preferowane, gdy usuwany jest cały tekst elementu. Największym powodem jest to, że utrzymuje ludzką czytelność.


1049
2017-08-01 17:31





Na Uwaga xkcd, Strona Bobby Tables ma dobrą radę, aby uniknąć niewłaściwej interpretacji danych użytkownika (w tym przypadku ciąg "Null") w zapytaniach SQL w różnych językach, w tym Zimna fuzja.

Z pytania nie wynika jednoznacznie, że jest to źródło problemu i biorąc pod uwagę rozwiązanie odnotowane w komentarzu do pierwszej odpowiedzi (osadzanie parametrów w strukturze) wydaje się prawdopodobne, że było to coś innego.


286
2018-04-27 20:00





Problem może tkwić w enkoderze SOAP Flexa. Spróbuj rozszerzyć koder SOAP w aplikacji Flex i debuguj program, aby zobaczyć, jak obsługiwana jest wartość pusta. Domyślam się, że minęło jak NaN (Nie numer). To zepsułoby proces unmarshalling komunikat SOAP kiedyś (przede wszystkim w JBoss 5 serwerów ...). Pamiętam, że rozszerzałem koder SOAP i dokładnie sprawdzałem sposób obsługi NaN.

(Na marginesie, czy oczekuje się, że zrobisz coś pożytecznego, jeśli identyfikator pracownika ma wartość Null, czy to nie jest kwestia sprawdzania poprawności? Mogę się mylić, ponieważ prawie nie znam wymagania ...)


235
2018-01-16 08:13



name = "Null" jest oczywiście przydatny, a nie widzę, jak powinien on być związany z NaN. - eckes


@ doc_180 miał właściwą koncepcję, z tym że skupiał się na liczbach, podczas gdy oryginalny plakat miał problemy z ciągami.

Rozwiązaniem jest zmiana mx.rpc.xml.XMLEncoder plik. To jest linia 121

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

[Spojrzałem na pakiet SDK Flex 4.5.1; numery linii mogą się różnić w innych wersjach]

Zasadniczo sprawdzanie poprawności nie powiedzie się, ponieważ "content is null", a zatem twój argument nie jest dodawany do wychodzącego pakietu SOAP; w ten sposób powodując brakujący błąd parametru.

Trzeba rozszerzyć tę klasę, aby usunąć sprawdzanie poprawności. Następnie jest wielka śnieżka w łańcuchu, modyfikująca SOAPEncoder, aby użyć zmodyfikowanego XMLEncodera, a następnie modyfikowanie Operacji, aby używał zmodyfikowanego SOAPEncodera, a następnie moidfying WebService do użycia alternatywnej klasy Operacji.

Spędziłem na nim kilka godzin, ale muszę iść dalej. Prawdopodobnie zajmie to dzień lub dwa.

Możesz po prostu naprawić linię XMLEncoder i zrobić łatanie małpy, aby użyć własnej klasy.

Dodam również, że jeśli przełączysz się na użycie RemoteObject / AMF z ColdFusion, wartość null jest przekazywana bez problemów.


Aktualizacja z 16.06.2013:

Mam jeszcze jeden niedawny dodatek do mojego ostatniego komentarza na temat RemoteObject / AMF. Jeśli używasz CF10; następnie właściwości z wartością pustą na obiekcie są usuwane z obiektu po stronie serwera. Musisz więc sprawdzić, czy istnieją właściwości przed uzyskaniem dostępu do niego, lub pojawi się błąd środowiska wykonawczego. Sprawdź tak:

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

Jest to zmiana w zachowaniu z CF9; gdzie właściwości null zmieniłyby się w puste łańcuchy.


Edytuj 12.06.2013

Ponieważ pojawiło się pytanie o to, w jaki sposób traktowane są wartości zerowe, jest to szybka przykładowa aplikacja, która pokazuje, w jaki sposób ciąg "null" będzie odnosił się do zarezerwowanego słowa "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>

Dane wyjściowe śledzenia:

łańcuch pusty nie jest równy zastrzeżonemu słowu null przy użyciu warunku! =

łańcuch pusty nie jest równy zastrzeżonemu słowu null przy użyciu warunku ==

łańcuch pusty nie jest równy zastrzeżonemu słowu null przy użyciu warunku ===


125
2018-05-03 15:51



@ Reboog711 Nazwisko pracownika jest dosłownie ciągiem "Null" jak w "Nazywam się Pat Null". Twoja odpowiedź nie przekazuje nazwiska pracownika. Odpowiadasz właśnie ukrywa fakt, że "Null" jest niewłaściwie wymuszony na koncepcji języka o wartości zerowej za pomocą metody appendChild () opisanej przez Bena Burnsa. Rezultatem jest wciąż brak systemu do czynienia z Panem lub Panią Null. - Maxx Daymon
@MaxxDaymon Myślę, że źle rozumiesz, jaka właściwie jest moja odpowiedź. Nie przedstawia rozwiązania; ale raczej wyjaśnienie, dlaczego pojawia się problem; i cytuje odpowiedni kod z Flex Framework. Moja ostatnia edycja jest prawdopodobnie niewłaściwie umieszczona; ponieważ omawia alternatywne podejście i nie jest bezpośrednio związane z pierwotnym pytaniem. - JeffryHouser
Jesteś na dobrej drodze, ale w tym momencie w kodzie content jest ciągiem "null"i "null" == null zwraca false, więc test zachowuje się zgodnie z przeznaczeniem. Zamiast tego uważam, że problem jest mieszanką tego, jak XML.appendChild obsługuje argument łańcuchowy, oraz w jaki sposób główny element XML zawierający tylko ciąg "null" można przekonwertować na literał null. - Ben Burns
@ Reboog711 Spójrz na moje skrzypce. "null"! = powracający true jest pożądane zachowanie tutaj. Gdyby stało się odwrotnie, odrzuciłoby to ciąg "null" z procesu kodowania, co w rzeczywistości byłoby przyczyną problemu. Jednak ponieważ test się powiódł, koder działa dalej, dopóki XML.appendChild nie odrzuci go z powodu błędu wymuszania. - Ben Burns
Bez obaw. Jeśli chcesz zobaczyć prawdziwy problem, dodaj var xml:XML = <root>null</root>; var s:String = (xml == null) ? "wtf? xml coerced to null?!!" : "xml not coerced to null."; trace(s); do próbki kodu. - Ben Burns


Przetłumacz wszystkie postacie na ich odpowiedniki w postaci heksadecymalnej. W tym przypadku, Null zostałby przekształcony w &#4E;&#75;&#6C;&#6C;


62
2018-04-30 19:03



Proszę tego nie robić. CDATA została stworzona do użycia w przypadkach, w których musisz uciec całemu blokowi tekstu. - Ben Burns
Mógłbym się mylić, ale nie sądzę, żebym przegrał, tylko dlatego, że tak nie było Twój rozwiązaniem jest to, jak powinno działać. Trzeba też pamiętać o problemach związanych z rozwiązaniem heurystycznym, ponieważ nie ma jednego oczywistego sposobu, o czym świadczy różnorodność zamieszczonych rozwiązań. Wreszcie, pamiętając o tym, że nie znam CF, czy dekoder nie po prostu utożsamia wewnętrzny tekst <message> <! [CDATA [NULL]]> </ message> z wewnętrznym tekstem <message> NULL </ wiadomość>? Jeśli tak, to czy CDATA jest naprawdę rozwiązaniem? - doogle
Zgadzam się, ponieważ jest to anty-wzór. Błąd w tym przypadku nie jest w CF, jest w ActionScript. Niemniej jednak podnieście dobry punkt. Dodam test do mojego skrzypiec na kodowanie CDATA. - Ben Burns


Łańcuchowanie a null wartość w ActionScript da ciąg znaków "NULL". Podejrzewam, że ktoś zdecydował, że dobrym pomysłem jest dekodowanie łańcucha "NULL" tak jak null, powodując tu złamanie - prawdopodobnie dlatego, że przechodzili null obiekty i uzyskiwanie ciągów w bazie danych, kiedy tego nie chcieli (więc sprawdź także tego rodzaju błąd).


49
2018-04-28 20:15



Tak, istnieje wiele możliwości, które wymagają zawężenia debugowania. 1) Czy WSDL jest tutaj wystarczająco ekspresywny, aby odróżnić "NULL" jako wartość ciągu i rzeczywistą wartość zerową (lub pominiętą)? 2) Jeśli tak, to czy klient prawidłowo koduje nazwisko (jako ciąg, a nie jako wartość zerową) 3) Jeśli tak, to czy usługa poprawnie interpretuje "NULL" jako ciąg znaków lub wymusza go na wartość pustą? - pimlottc


Jako narzędzie hakerskie można rozważyć specjalne traktowanie po stronie klienta, konwersję łańcucha "Null" na coś, co nigdy nie wystąpi, na przykład XXNULLXX i konwersję z powrotem na serwer.

Nie jest ładny, ale może rozwiązać problem w takim przypadku granicznym.


36
2018-04-28 08:43



XXNULLXX również może być nazwą. Nie wiesz. Może ludzie w Indonezji nie mają nazwiska i w razie potrzeby używają wariantu XXX jako swojego nazwiska. - gb.
Albo, janno, zawsze jest CDATA ... - Ben Burns
Ta sama koncepcja, ale zaktualizuj wszystkie nazwy w bazie danych, a następnie wpisz ją z pewnym charakterem (1Null, 1Smith). Pozbądź się tej postaci w kliencie. Oczywiście może to być praca z roztoczami niż rozwiązanie Reboog. - bobpaul
@BenBurns Tak, ale co jeśli chcę nazwać moje dziecko &#78;&#117;&#108;&#108;? - Sirens
@Sirens To nie jest problem. Jeśli moje nazwisko brzmi "<"> ", to spodziewam się, że jest odpowiednio zmienione jako" & quot; ", co jest oczywiste. Prawdziwy problem polega na tym, że aplikacja zachowuje się tak, jakby używała czarnej listy dla nazw. - Mr Lister


Cóż, myślę, że implementacja Flexa enkodera SOAP wydaje się nieprawidłowo szeregować wartości null. Serializacja ich jako String Null nie wydaje się dobrym rozwiązaniem. Formalnie poprawna wersja wydaje się przekazywać wartość pustą jako:

<childtag2 xsi:nil="true" />

Tak więc wartość "Null" byłaby niczym innym jak poprawnym łańcuchem, którego dokładnie szukamy.

Myślę, że rozwiązanie tego problemu w Apache Flex nie powinno być tak trudne do zrobienia. Polecam otwarcie wydania Jira lub skontaktowanie się z chłopakami z listy dyskusyjnej apache-flex. Jednak to naprawi tylko stronę klienta. Nie mogę powiedzieć, czy ColdFusion będzie mógł pracować z wartościami null zakodowanymi w ten sposób.

Zobacz także wpis na blogu Radu Cotescu Jak wysłać wartości null w żądaniach soapUI.


30
2017-07-17 07:56



Tutaj są dobre informacje, więc nie będę głosował, ale pomyślałem, że warto to komentować. Domyślnie XMLEncoder.as faktycznie zakoduje wartość true null wartość poprawnie, przez ustawienie xsi:nil="true" na elemencie. Wydaje się, że problem dotyczy sposobu działania ActionScript XML sam typ (nie enkoder) obsługuje ciąg znaków "null". - Ben Burns