วิธีส่ง“ Null” (นามสกุลจริง!) ไปยังบริการเว็บ SOAP ใน ActionScript 3


4635

เรามีพนักงานที่มีนามสกุลว่าง แอปพลิเคชันค้นหาพนักงานของเราถูกฆ่าเมื่อนามสกุลนั้นถูกใช้เป็นคำค้นหา (ซึ่งเกิดขึ้นบ่อยครั้งในขณะนี้) ข้อผิดพลาดที่ได้รับ (ขอบคุณ Fiddler!) คือ:

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

น่ารักใช่มั้ย

stringประเภทพารามิเตอร์

ฉันใช้:

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

โปรดทราบว่าข้อผิดพลาดจะไม่เกิดขึ้นเมื่อเรียกเว็บเซอร์เป็นวัตถุจากหน้า ColdFusion


6
อาจไม่ช่วยคุณได้มากนักกับปัญหาที่เฉพาะเจาะจง แต่ SOAP 1.2 อนุญาตให้มีค่าที่ไม่สามารถใช้ได้ดูw3.org/TR/2001/WD-soap12-20010709/#_Toc478383513
JensG

6
ฉันรู้สึกว่ามันเกี่ยวข้องกับ Dave Null
George Gibson

2
อย่างน้อยก็ไม่เกี่ยวข้องกับ Chuck Norris นี่คือเหตุผลที่จะอยู่ห่างจากเขาในรหัส: codesqueeze.com/…
SDsolar

42
พนักงานพิจารณาเปลี่ยนชื่อของเขาหรือไม่?
Tatranskymedved

11
เขาควรพิจารณาซื้อสุนัขตัวชี้และเรียกเขาว่า NullPointer
Antonio Alvarez

คำตอบ:


1108

ติดตามมัน

ตอนแรกฉันคิดว่านี่เป็นข้อผิดพลาดการบีบบังคับที่nullได้รับการข่มขู่"null"และการทดสอบ"null" == nullผ่าน มันไม่ใช่. ฉันสนิท แต่ก็ผิดมาก ขอโทษด้วยกับเรื่องนั้น!

ฉันทำสิ่งที่เล่นซอบน wonderfl.netและติดตามผ่านโค้ดมาmx.rpc.xml.*มากมาย ที่บรรทัดที่ 1795 ของXMLEncoder(ในแหล่ง 3.5) ในsetValueทั้งหมด XMLEncoding เดือดลงไป

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

ซึ่งเป็นหลักเช่นเดียวกับ:

currentChild.appendChild("null");

รหัสนี้ตามซอตัวยงของฉันคืนค่าองค์ประกอบ XML เปล่า แต่ทำไม

สาเหตุ

ตามที่ commenter Justin Mclean รายงานข้อผิดพลาดFLEX-33664ต่อไปนี้เป็นผู้ร้าย (ดูการทดสอบสองครั้งล่าสุดในซอของฉันที่ตรวจสอบเรื่องนี้):

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
}

เมื่อcurrentChild.appendChildถูกส่งผ่านสตริง"null"มันจะแปลงเป็นอิลิเมนต์รูท XML ด้วยข้อความnullก่อนจากนั้นทดสอบองค์ประกอบนั้นกับตัวอักษรว่าง นี่คือการทดสอบความเท่าเทียมกันที่อ่อนแอดังนั้น XML ที่มีค่า null จะถูกบังคับให้เป็นประเภท null หรือประเภท null นั้นถูกรวมเข้ากับองค์ประกอบรูท xml ที่มีสตริงเป็น "null" และการทดสอบจะผ่านไปในที่ที่ควรจะล้มเหลว วิธีแก้ไขหนึ่งอาจใช้การทดสอบความเสมอภาคที่เข้มงวดทุกครั้งเมื่อตรวจสอบ XML (หรืออะไรก็ตาม) สำหรับ "nullness"

สารละลาย

วิธีแก้ปัญหาที่เหมาะสมเท่านั้นที่ฉันสามารถคิดสั้นของการแก้ไขข้อผิดพลาดในทุกรุ่นแช่งของ ActionScript คือการเขตการทดสอบสำหรับ "null" และหลบหนีพวกเขาเป็นค่า CDATA

ค่า CDATA เป็นวิธีที่เหมาะสมที่สุดในการเปลี่ยนแปลงค่าข้อความทั้งหมดซึ่งอาจทำให้เกิดปัญหาการเข้ารหัส / ถอดรหัส ตัวอย่างเช่นการเข้ารหัส Hex มีไว้สำหรับอักขระแต่ละตัว ค่า CDATA เป็นที่ต้องการเมื่อคุณกำลังหลบหนีเนื้อหาทั้งหมดขององค์ประกอบ เหตุผลที่ดีที่สุดสำหรับสิ่งนี้คือมันสามารถอ่านได้ของมนุษย์


298

ในการบันทึก xkcdที่เว็บไซต์ของตารางบ๊อบบี้มีคำแนะนำที่ดีเพื่อหลีกเลี่ยงการตีความที่ไม่เหมาะสมของข้อมูลผู้ใช้ (ในกรณีนี้สตริง "Null") ใน SQL แบบสอบถามในภาษาต่าง ๆ รวมทั้งColdFusion

มันไม่ชัดเจนจากคำถามที่ว่านี่คือที่มาของปัญหาและได้รับการแก้ปัญหาที่ระบุไว้ในความคิดเห็นที่คำตอบแรก (ฝังพารามิเตอร์ในโครงสร้าง) ดูเหมือนว่ามีแนวโน้มว่ามันเป็นอย่างอื่น


239

ปัญหาอาจเกิดจากตัวเข้ารหัส SOAP ของ Flex ลองขยายตัวเข้ารหัส SOAP ในแอปพลิเคชัน Flex ของคุณและตรวจแก้จุดบกพร่องโปรแกรมเพื่อดูวิธีจัดการค่า Null

ฉันเดาว่ามันผ่านเป็นNaN (ไม่ใช่ตัวเลข) สิ่งนี้จะทำให้ข้อความ SOAP ไม่สามารถตรวจสอบได้ในบางครั้ง (โดยเฉพาะอย่างยิ่งในเซิร์ฟเวอร์JBoss 5 ... ) ฉันจำการขยายตัวเข้ารหัส SOAP และทำการตรวจสอบอย่างชัดเจนเกี่ยวกับวิธีจัดการ NaN


12
name = "Null" มีประโยชน์แน่นอนและฉันไม่เห็นว่ามันควรเกี่ยวข้องกับ NaN อย่างไร
eckes

129

@ doc_180 มีแนวคิดที่ถูกต้องยกเว้นว่าเขามุ่งเน้นไปที่ตัวเลขในขณะที่โปสเตอร์ดั้งเดิมมีปัญหากับสตริง

ทางออกคือการเปลี่ยนmx.rpc.xml.XMLEncoderไฟล์ นี่คือบรรทัดที่ 121:

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

(ฉันดู Flex 4.5.1 SDK; หมายเลขบรรทัดอาจแตกต่างกันในเวอร์ชันอื่น)

โดยทั่วไปการตรวจสอบความถูกต้องล้มเหลวเนื่องจาก 'เนื้อหาเป็นโมฆะ' ดังนั้นอาร์กิวเมนต์ของคุณจะไม่ถูกเพิ่มลงใน SOAP Packet ขาออก จึงทำให้เกิดข้อผิดพลาดพารามิเตอร์ที่หายไป

คุณต้องขยายคลาสนี้เพื่อลบการตรวจสอบ จากนั้นมีก้อนหิมะขนาดใหญ่ขึ้นบนโซ่ปรับเปลี่ยน SOAPEncoder เพื่อใช้ XMLEncoder ที่แก้ไขแล้วจากนั้นปรับเปลี่ยนการดำเนินการเพื่อใช้ SOAPEncoder ที่แก้ไขแล้วจากนั้น moidfying WebService เพื่อใช้คลาสการดำเนินงานสำรองของคุณ

ฉันใช้เวลาสองสามชั่วโมง แต่ฉันต้องเดินหน้าต่อไป อาจใช้เวลาหนึ่งหรือสองวัน

คุณอาจสามารถแก้ไขบรรทัด XMLEncoder และทำการแก้ไขลิงเพื่อใช้คลาสของคุณเอง

ฉันจะเพิ่มด้วยถ้าคุณสลับไปใช้ RemoteObject / AMF กับ ColdFusion ค่า null จะถูกส่งผ่านโดยไม่มีปัญหา


ปรับปรุง 11/16/2013 :

ฉันมีอีกหนึ่งความเห็นล่าสุดของฉันเกี่ยวกับ RemoteObject / AMF หากคุณใช้ ColdFusion 10; ดังนั้นคุณสมบัติที่มีค่า Null บนวัตถุจะถูกลบออกจากวัตถุฝั่งเซิร์ฟเวอร์ ดังนั้นคุณต้องตรวจสอบคุณสมบัติที่มีอยู่ก่อนที่จะเข้าถึงมิฉะนั้นคุณจะได้รับข้อผิดพลาดรันไทม์

ตรวจสอบดังนี้:

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

นี่คือการเปลี่ยนแปลงพฤติกรรมจาก ColdFusion 9; โดยที่คุณสมบัติ null จะเปลี่ยนเป็นสตริงว่าง


แก้ไข 12/6/2013

เนื่องจากมีคำถามเกี่ยวกับวิธีปฏิบัติต่อ nulls ต่อไปนี้เป็นตัวอย่างแอปพลิเคชันอย่างรวดเร็วเพื่อแสดงให้เห็นว่าสตริง "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>

ผลลัพธ์การติดตามคือ:

สตริง null ไม่เท่ากับคำสงวน null โดยใช้เงื่อนไข! =

สตริง null ไม่เท่ากับคำสงวน null โดยใช้เงื่อนไข ==

สตริง null ไม่เท่ากับคำสงวน null โดยใช้เงื่อนไข ===


8
@ Reboog711 นามสกุลของพนักงานคือสตริง "Null" ตามที่ปรากฏใน "My name is Pat Null" คำตอบของคุณไม่สามารถผ่านนามสกุลของพนักงานได้ คุณตอบเพียงซ่อนความจริงที่ว่า "Null" ถูกบังคับให้เข้ากับแนวคิดภาษาโมฆะโดยวิธี appendChild () ตามที่อธิบายโดย Ben Burns อย่างไม่เหมาะสม ผลที่ได้คือความล้มเหลวของระบบในการจัดการกับนายหรือนางสาวนัล
Maxx Daymon

2
@ MaxxDaymon ฉันคิดว่าคุณเข้าใจผิดว่าคำตอบของฉันคืออะไร มันไม่ได้นำเสนอวิธีแก้ปัญหา แต่เป็นคำอธิบายว่าทำไมปัญหาเกิดขึ้น และเสนอราคารหัสที่เกี่ยวข้องจาก Flex Framework การแก้ไขล่าสุดของฉันอาจหายไป มันอธิบายวิธีอื่นและไม่เกี่ยวข้องโดยตรงกับคำถามเดิม
JeffryHouser

1
คุณกำลังเรียงลำดับอย่างถูกต้อง แต่ ณ จุดนั้นในรหัสcontentคือสตริง"null"และ "null" == null ส่งกลับค่า false ดังนั้นการทดสอบจะทำงานตามที่ต้องการ แต่ฉันเชื่อว่าปัญหาคือการผสมผสานของวิธีการที่ XML.appendChild จัดการกับอาร์กิวเมนต์สตริงและองค์ประกอบ XML ของรูทที่มีเฉพาะสตริง "null" เท่านั้นที่สามารถถูกรวมเข้ากับตัวอักษรnullได้
Ben Burns

@ Reboog711 ลองดูที่ซอของฉัน "null"! = null` return trueเป็นพฤติกรรมที่ต้องการที่นี่ หากตรงข้ามเกิดขึ้นจะเป็นการละทิ้งสตริง "null" จากกระบวนการเข้ารหัสซึ่งอันที่จริงแล้วเป็นสาเหตุของปัญหา อย่างไรก็ตามเนื่องจากการทดสอบนี้สำเร็จตัวเข้ารหัสจะดำเนินต่อไปจนกว่า XML.appendChild จะละทิ้งเนื่องจากข้อผิดพลาดของการบีบบังคับ
Ben Burns

4
ไม่ต้องห่วง. หากคุณต้องการที่จะเห็นปัญหาที่แท้จริงเพิ่มvar xml:XML = <root>null</root>; var s:String = (xml == null) ? "wtf? xml coerced to null?!!" : "xml not coerced to null."; trace(s);ไปยังตัวอย่างรหัสของคุณ
Ben Burns

65

แปลอักขระทั้งหมดเป็นรายการเทียบเท่าฐานสิบหก ในกรณีนี้Nullจะถูกแปลงเป็น&#4E;&#75;&#6C;&#6C;


41
โปรดอย่าทำเช่นนี้ CDATA ถูกสร้างขึ้นเพื่อใช้ในกรณีที่คุณต้องการหลีกเลี่ยงข้อความทั้งหมด
Ben Burns

4
ฉันอาจจะผิด แต่ฉันไม่คิดว่า downvoting เพียงเพราะมันไม่ใช่ทางออกของคุณคือมันควรจะทำงานอย่างไร นอกจากนี้คุณต้องจำไว้ว่าปัญหานั้นเรียกร้องให้มีวิธีแก้ปัญหาแบบฮิวริสติกเนื่องจากไม่มีวิธีที่ชัดเจนวิธีหนึ่งที่เห็นได้ชัดจากการแก้ปัญหาที่โพสต์หลากหลาย ท้ายที่สุดจำไว้ว่าฉันไม่รู้ CF ไม่ถอดรหัสแค่เอาข้อความภายในของ <message><! ข้อความ>? ถ้าเป็นเช่นนั้น CDATA จะเป็นทางออกจริงๆหรือไม่?
doogle

7
ฉันลงคะแนนเพราะนี่เป็นรูปแบบการต่อต้าน ข้อผิดพลาดในกรณีนี้ไม่ได้อยู่ใน CF แต่อยู่ใน ActionScript อย่างไรก็ตามคุณยกประเด็นที่ดีอย่างไรก็ตาม ฉันจะเพิ่มการทดสอบซอของฉันสำหรับการเข้ารหัส CDATA
Ben Burns

51

Stringifying nullค่าในActionScript"NULL"จะให้สตริง ความสงสัยของฉันคือมีคนตัดสินใจว่ามันจึงเป็นความคิดที่ดีที่จะถอดรหัสสตริง"NULL"ที่nullทำให้เกิดการแตกที่คุณเห็นที่นี่ - อาจเป็นเพราะพวกเขาผ่านnullวัตถุและรับสตริงในฐานข้อมูลเมื่อพวกเขาไม่ต้องการ (โปรดตรวจสอบข้อผิดพลาดประเภทนั้นด้วย)


ใช่มีความเป็นไปได้มากมายที่นี่ซึ่งจะต้องใช้การแก้ไขข้อบกพร่องเพิ่มเติมเพื่อ จำกัด ขอบเขตให้แคบลง 1) WSDL ใช้ที่นี่อย่างชัดเจนเพียงพอที่จะแยกแยะความแตกต่างระหว่าง "NULL" เป็นค่าสตริงและค่า Null (หรือละเว้น) จริงหรือไม่? 2) ถ้าเป็นเช่นนั้นลูกค้าเข้ารหัสชื่ออย่างถูกต้อง (เป็นสตริงและไม่ใช่ตัวอักษรที่เป็นโมฆะ) 3) ถ้าเป็นเช่นนั้นบริการตีความอย่างถูกต้องว่า "NULL" เป็นสตริงหรือบังคับใช้กับค่า Null หรือไม่?
pimlottc

39

ในฐานะที่เป็นแฮ็คคุณสามารถพิจารณาการจัดการพิเศษทางฝั่งไคลเอ็นต์แปลงสตริง 'Null' เป็นสิ่งที่จะไม่เกิดขึ้นเช่น XXNULLXX และแปลงกลับบนเซิร์ฟเวอร์

มันไม่สวย แต่ก็อาจแก้ปัญหากรณีดังกล่าวได้


32
XXNULLXX อาจมีชื่อด้วย คุณไม่รู้ บางทีคนในอินโดนีเซียไม่มีนามสกุลและใช้ XXX เป็นนามสกุลเมื่อจำเป็น
gb

3
แนวคิดเดียวกัน แต่อัพเดตชื่อทั้งหมดในฐานข้อมูลและนำหน้าด้วยอักขระบางตัว (1Null, 1Smith) ถอดตัวละครนั้นออกจากไคลเอนต์ แน่นอนว่านี่อาจเป็นผลไรมากกว่าวิธีแก้ปัญหาของ Reboog
bobpaul

14
@BenBurns ใช่ แต่สิ่งที่ถ้าผมต้องการที่จะตั้งชื่อเด็กของฉัน&#78;&#117;&#108;&#108;?
ไซเรน

@ ไซเรนนั่นไม่ใช่ปัญหา หากชื่อของฉันคือ "<& quot;>" ฉันก็คาดหวังว่าจะได้รับการยกเว้นว่า & quot; & lt; & amp; quot; & gt; & gt; & นั่นจะไปโดยไม่พูด ปัญหาที่แท้จริงคือแอปพลิเคชันทำงานราวกับว่ามันใช้บัญชีดำสำหรับชื่อ
Mr Lister

30

ฉันเดาว่าการติดตั้ง SOAP Encoder ของ Flex นั้นดูเหมือนว่าจะทำให้อนุกรมเป็นโมฆะไม่ถูกต้อง การทำให้เป็นอันดับเป็น String Null ดูเหมือนจะไม่ใช่ทางออกที่ดี ดูเหมือนว่าเวอร์ชั่นที่ถูกต้องอย่างเป็นทางการจะต้องผ่านค่า Null เป็น:

<childtag2 xsi:nil="true" />

ดังนั้นค่าของ "Null" จะไม่มีอะไรอื่นนอกจากสตริงที่ถูกต้องซึ่งเป็นสิ่งที่คุณกำลังมองหา

ฉันเดาว่าการแก้ไขนี้ใน Apache Flex ไม่น่าจะทำได้ยาก ฉันอยากจะแนะนำให้เปิดปัญหาจิราหรือติดต่อพวกเมลลิ่งของ apache-flex อย่างไรก็ตามสิ่งนี้จะแก้ไขฝั่งไคลเอ็นต์เท่านั้น ฉันไม่สามารถบอกได้ว่า ColdFusion จะสามารถทำงานกับค่า Null ที่เข้ารหัสด้วยวิธีนี้ได้หรือไม่

ดูยังโพสต์บล็อก Radu Cotescu ของวิธีการส่งค่า null ในคำขอ


6
มีข้อมูลที่ดีที่นี่ดังนั้นฉันจะไม่ลงคะแนน แต่ฉันคิดว่ามันคุ้มค่ากับความคิดเห็น โดยค่าเริ่มต้น XMLEncoder.as จะเข้ารหัสnullค่าจริงอย่างถูกต้องโดยการตั้งค่าxsi:nil="true"องค์ประกอบ ปัญหาจริงดูเหมือนจะเป็นในทาง ActionScript XMLประเภทตัวเอง (ไม่ได้เข้ารหัส) "null"จัดการสตริง
Ben Burns

22

มัน kludge แต่สมมติว่ามีความยาวต่ำสุดสำหรับSEARCHSTRINGตัวอย่างเช่น 2 ตัวอักษรพารามิเตอร์ที่ตัวละครตัวที่สองและผ่านเป็นพารามิเตอร์ที่สองแทนและให้พวกเขากลับมารวมกันเมื่อมีการดำเนินการสอบถามไปยังฐานข้อมูลsubstringSEARCHSTRINGSEARCHSTRING1 ("Nu")SEARCHSTRING2 ("ll"). Concatenate


32
CDATA ถูกเพิ่มในข้อมูลจำเพาะ XML เพื่อหลีกเลี่ยง kludges ประเภทนี้
Ben Burns

8
ไม่จำเป็นต้องหลบหนี "Null" ด้วย CDATA ไม่จำเป็นต้องมีคำสำคัญว่างเปล่าใน XML
eckes

6
เห็นด้วยกับ @eckes ฉันไม่เข้าใจว่าทำไมถึงมีการพูดคุยของ CDATA นี้ทั้งหมด CDATA มีประโยชน์ในการยกเว้นอักขระที่มีความหมายพิเศษใน XML ไม่มี: n, u, lมีความหมายพิเศษในรูปแบบ XML "NULL" และ "<! [CDATA [NULL]]>" จะเหมือนกับตัวแยกวิเคราะห์ XML
jasonkarns

9
@ jasonkarns - ฉันเห็นด้วย 100% ว่าไม่ควรมีอะไรพิเศษเกี่ยวกับสตริง / ข้อความโหนดNULLแต่จะเป็นความคล่องแคล่ว<blah>null</blah>และ<blah><![CDATA[null]]>ไม่เหมือนกับตัวแยกวิเคราะห์ XML พวกเขาควรให้ผลลัพธ์ที่เหมือนกัน แต่ลอจิกไหลสำหรับการจัดการพวกเขาจะแตกต่างกัน มันเป็นเอฟเฟกต์นี้ที่เราใช้ประโยชน์จากการแก้ปัญหาข้อบกพร่องในการนำ flex XML ไปใช้งาน ฉันสนับสนุนเรื่องนี้มากกว่าวิธีการอื่น ๆ เนื่องจากมันรักษาความสามารถในการอ่านของข้อความและไม่มีผลข้างเคียงสำหรับตัวแยกวิเคราะห์อื่น
Ben Burns
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.