views:

579

answers:

5

We are developing an app with a Flex frontend and a C# backend, connected through web services. We are using the FLex Builder 3's Web Service Manager to autogenerate the webservice classes. The problem araise when Flex serialize our objects, for example, when we have a Number property with no value, this is serialized as NaN, and our backend doesn't know about NaN. Another example is when we serialize a cyclic reference, we get a stack over flow exception. I know in java, for example, you can configure the way xstream work with cyclic reference... So, the question is, can we change the way Flex serialize the objects so C# can work with this frontend? Is there any issue we should know about how flex serialize objects? Thanks! Jorge

A: 

Hi Jorge!

In my understanding, when you make use of Flex Bluider's Web Service Manager, the proxy ActionScript classes are automatically generated for every webservice you create. The serialization process uses those classes when hitting one of your webservice. You could edit the properties of those classes so that they are always procesable on the C# side (and this way get rid of the NaN values).

Another option I see would be to write your own custom code to process objects from and to XML. This Adobe article can get you started.

jdecuyper
A: 

I am not sure how to change the serialization of the auto-generated classes but I'll try to offer some help below:

What your probably looking for (although I've never used this I just see it mentioned all the time):

Things I have done:

  • Use JSON which can be done easily with as3corelib

Another idea I've never tried:

In regards to the issue your facing:

  • I've had numerous issues with serializing objects to Java, so test thoroughly
  • I tried using auto-generated web services with .Net which has serialization issues as well. The auto-generation seems to change quite a bit when updating SDKs but I still had no luck with my services and never found the root cause.
Brandon
+1  A: 

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.

Akash Kava
A: 

Hello, Jorge!

May be I have found a decision for your problem.

If you use autogenerated classes in FlexBuilder3 you can catch and modify the outgoing soap message. It is easy to do in the "call()" function of your "Base[ServiceName]" class.

All what you need to do is to modify the "soap" variable before the string

message.body = soap.toString();

In my case I have made the cleanXML function (see below). This function deletes all XML elements which are equal to "NaN" or which have an attribute xsi:nil='true'

private function cleanXML(xml:XML, qn:QName):void{
 if (XMLList(xml).hasSimpleContent()){
  if ((xml.valueOf() == "NaN") || (xml.attribute(qn) == true)){
   delete xml.parent().children()[xml.childIndex()];
  }
 }else{  
  for each (var item:XML in xml.children()){
   cleanXML(item, qn);
  } 
 }
}

So the mentioned section of the call() function is:

    var soapList:XML;
    soapList = soap as XML;

    var qn:QName = new QName(soapList.namespace("xsi"), "nil");
    cleanXML(soapList, qn);   

    message.body = soapList.toString();

I know that this decision is not good, by in my situation it works perfectly!

Antonio
A: 

You mean you put a method in generated code? That doesn't sound like a good solution, everytime you import a wsdl you loose your clean method.

wiibart