如何在flex中为c#后端序列化对象

时间:2009-09-26 00:25:45

标签: c# flex actionscript-3 web-services serialization

我们正在开发一个带有Flex前端和C#后端的应用程序,通过Web服务连接。 我们使用FLex Builder 3的Web服务管理器来自动生成Web服务类。 当Flex序列化我们的对象时,问题是,例如,当我们有一个没有值的Number属性时,这被序列化为NaN,而我们的后端不知道NaN。另一个例子是当我们序列化循环引用时,我们得到一个堆栈溢出异常。  我知道在java中,例如,你可以配置xstream使用循环引用的方式......所以,问题是,我们可以改变Flex序列化对象的方式,这样C#可以使用这个前端吗?关于flex序列化对象有什么问题我们应该知道吗? 谢谢! 乔治

4 个答案:

答案 0 :(得分:1)

我认为您应该考虑一些不同的设计,我们也有类似的问题,但我们开发了以下解决方案。

仅原始参数

仅在Web服务方法参数(字符串,整数)等中定义基本类型。

例如,你有一个班级,

class Person{
    long PersonID;
    long MembershipID;
    string Name;
}

你想只改变后端的“Name”属性,事实是,你不应该相信你的前端,你应该认为前端很容易被破坏并且可以发送错误的数据,比如在这种情况下的MembershipID就是字段永远不会被前端修改。

您可以编写Person将正确保存的代码,但有人可以轻松阅读WSDL并损坏代码。

所以不要这样。

[WebMethod] 
public void SavePerson(Person p){
    p.Save(); <-- this is dangerous
}

我们使用

[WebMethod] 
public void SavePersonName(long personID, string name){
    Person p = GetPersonByID(personID);
    p.Name = name;
    p.Save();
}

我知道很多人会争辩说这会导致更多的编码以及更多的往返服务器,但是使用Specialized Wrapper Classes也可以避免往返。

在参数中使用包装类

// 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();
    }
}

通过这种方式,您可以减少往返次数,您还可以组织包装类来包含/排除可以删除循环依赖项及其安全性的项目。

是的我知道这需要更多的工作,但这是安全的方法。

答案 1 :(得分:0)

根据我的理解,当您使用Flex Bluider的Web Service Manager时,会为您创建的每个Web服务自动生成代理ActionScript类。序列化过程在点击您的一个Web服务时使用这些类。您可以编辑这些类的属性,以便它们始终可以在C#端处理(这样就可以除去NaN值)。

我看到的另一个选择是编写自己的自定义代码来处理来自XML的对象。 This Adobe article可以帮助您入门。

答案 2 :(得分:0)

我不知道如何更改自动生成的类的序列化,但我会尝试在下面提供一些帮助:

你可能正在寻找什么(虽然我从来没有使用过这个,但我只是看到它一直提到):

我做过的事情:

  • 使用JSON,可以使用as3corelib
  • 轻松完成

我从未尝试过的另一个想法:

关于你面临的问题:

  • 我在将对象序列化为Java时遇到了很多问题,因此请彻底测试
  • 我尝试使用.Net自动生成的Web服务,它也有序列化问题。更新SDK时,自动生成似乎发生了相当大的变化,但我仍然没有运气,而且从未找到根本原因。

答案 3 :(得分:0)

可能我已经找到了解决问题的决定。

如果在FlexBuilder3中使用自动生成的类,则可以捕获并修改传出的soap消息。在“Base [ServiceName]”类的“call()”函数中很容易做到。

您需要做的就是在字符串

之前修改“soap”变量
message.body = soap.toString();

在我的情况下,我已经制作了cleanXML函数(见下文)。此函数删除所有等于“NaN”或具有属性xsi的XML元素: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);
        }   
    }
} 

所以call()函数的上述部分是:

    var soapList:XML;
    soapList = soap as XML;

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

    message.body = soapList.toString();

我知道这个决定并不好,在我的情况下它完美无缺!