I think you should consider a little different design, we also had similar problem but we developed following solution.
Only Primitive Arguments
Define only primitive types in Web Service Method Arguments (string, int) etc..
For example you have a class,
class Person{
long PersonID;
long MembershipID;
string Name;
}
And you want to only change "Name" property on the backend, the truth is, you should not trust your Frontend, you should treat that frontend can easily be compromised and can send wrong data, like MembershipID in this case is the field not to be modified by frontend ever.
You may write your code that Person will save correctly, but someone can easily read WSDL and harm the code.
So instead of this.
[WebMethod]
public void SavePerson(Person p){
p.Save(); <-- this is dangerous
}
we use
[WebMethod]
public void SavePersonName(long personID, string name){
Person p = GetPersonByID(personID);
p.Name = name;
p.Save();
}
I know many will argue that this will cause more coding as well as more roundtrips to server, however roundtrips can also be avoided by using Specialized Wrapper Classes.
Use of Wrapper Classes in Arguments
// I will only define the fields I want to pass to server
// this needs to be done at backend level
class PersonAddressWrapper{
long PersonAddressID;
string AddressLine1;
string AddressLine2;
string ZipCode;
string City;
string Country;
}
class PersonWrapper{
long PersonID;
string Name;
PersonAddressWrapper[] Addresses;
}
[WebMethod]
public void SavePerson(PersonWrapper pw){
Person p = GetPersonByID(pw.PersonID);
p.Name = pw.Name;
p.Save();
foreach(PersonAddressWrapper paw in pw.Addresses){
PersonAddress pa = GetPersonAddressByID(paw.PersonAddressID);
Copy(pa,paw);
pa.Save();
}
}
This way you can reduce the round trips, you can also organize wrapper classes to include/exclude items that can remove your cyclic dependency and its safe too.
Yes I know it requires more work, but this is the safe method.
Tracking it down
At first I thought this was a coercion bug where null
was getting coerced to "null"
and a test of "null" == null
was passing. It's not. I was close, but so very, very wrong. Sorry about that!
I've since done lots of fiddling on wonderfl.net and tracing through the code in mx.rpc.xml.*
. At line 1795 of XMLEncoder
(in the 3.5 source), in setValue
, all of the XMLEncoding boils down to
currentChild.appendChild(xmlSpecialCharsFilter(Object(value)));
which is essentially the same as:
currentChild.appendChild("null");
This code, according to my original fiddle, returns an empty XML element. But why?
Cause
According to commenter Justin Mclean on bug report FLEX-33664, the following is the culprit (see last two tests in my fiddle which verify this):
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
}
When currentChild.appendChild
is passed the string "null"
, it first converts it to a root XML element with text null
, and then tests that element against the null literal. This is a weak equality test, so either the XML containing null is coerced to the null type, or the null type is coerced to a root xml element containing the string "null", and the test passes where it arguably should fail. One fix might be to always use strict equality tests when checking XML (or anything, really) for "nullness."
Solution
The only reasonable workaround I can think of, short of fixing this bug in every damn version of ActionScript, is to test fields for "null" and
escape them as CDATA values.
CDATA values are the most appropriate way to mutate an entire text value that would otherwise cause encoding/decoding problems. Hex encoding, for instance, is meant for individual characters. CDATA values are preferred when you're escaping the entire text of an element. The biggest reason for this is that it maintains human readability.
Best Answer
Is this a SOAP service implementation? Are you using the FlashBuilder "import wsdl" feature, or something else?
You can use Flash builder to import the WSDL and dynamically generate the AS classes. You should have the derived classes imported there. When your data comes in, you'll need to cast the fruit objects into their correct child classes. Check to make sure your WSDL is properly constructed - I don't see why sending the collection in that way would pose a problem for Flex.
If you could give more detailed information on the web service architecture it might help us give a more detailed answer.