如何在flex中为c#后端序列化对象
我们正在开发一款具有Flex前端和C#后端的应用程序,通过web服务连接。 我们使用FlexBuilder3的Web服务管理器自动生成Web服务类。 当Flex序列化我们的对象时,问题就出现了,例如,当我们有一个没有值的Number属性时,它被序列化为NaN,而我们的后端不知道NaN。另一个例子是当我们序列化一个循环引用时,我们得到一个堆栈溢出异常。 例如,我知道在java中,您可以配置xstream使用循环引用的工作方式。。。所以,问题是,我们能否改变Flex序列化对象的方式,使C#能够使用这个前端?关于flex如何序列化对象,我们应该知道哪些问题? 谢谢如何在flex中为c#后端序列化对象,c#,apache-flex,actionscript-3,web-services,serialization,C#,Apache Flex,Actionscript 3,Web Services,Serialization,我们正在开发一款具有Flex前端和C#后端的应用程序,通过web服务连接。 我们使用FlexBuilder3的Web服务管理器自动生成Web服务类。 当Flex序列化我们的对象时,问题就出现了,例如,当我们有一个没有值的Number属性时,它被序列化为NaN,而我们的后端不知道NaN。另一个例子是当我们序列化一个循环引用时,我们得到一个堆栈溢出异常。 例如,我知道在java中,您可以配置xstream使用循环引用的工作方式。。。所以,问题是,我们能否改变Flex序列化对象的方式,使C#能够使用这
Jorge据我所知,当您使用Flex Bluider的Web服务管理器时,会为您创建的每个Web服务自动生成代理操作脚本类。序列化过程在访问某个Web服务时使用这些类。您可以编辑这些类的属性,以便它们始终可以在C#端进行处理(这样就可以去掉NaN值)
我看到的另一个选择是编写自己的自定义代码来处理XML和XML之间的对象。我不知道如何更改自动生成类的序列化,但我将尝试提供以下帮助: 您可能在寻找什么(尽管我从未使用过此功能,但我一直看到有人提到它):
- 使用JSON,这可以很容易地用
- 与Actionscript插件一起使用
- 我在将对象序列化到Java时遇到了很多问题,所以请彻底测试
- 我尝试在.Net中使用自动生成的web服务,它也有序列化问题。在更新SDK时,自动生成似乎发生了很大的变化,但我的服务仍然不走运,也没有找到根本原因
我想你应该考虑一下不同的设计,我们也有类似的问题,但是我们开发了以下的解决方案。 仅原语参数
// 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();
}
}
仅在Web服务方法参数(字符串、int)等中定义基元类型
比如你有一门课
class Person{
long PersonID;
long MembershipID;
string Name;
}
你只想改变后端的“Name”属性,事实是,你不应该信任你的前端,你应该认为前端很容易被破坏,并且可以发送错误的数据,比如在这种情况下,MembershipID是前端永远不能修改的字段
您可以编写自己的代码,让他人正确保存,但有人很容易读取WSDL并破坏代码
所以不是这个
[WebMethod]
public void SavePerson(Person p){
p.Save(); <-- this is dangerous
}
我知道很多人会争辩说,这将导致更多的编码以及到服务器的更多往返,然而,通过使用专门的包装器类也可以避免往返
在参数中使用包装类
// 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();
}
}
通过这种方式,您可以减少往返,还可以组织包装器类以包含/排除可以删除循环依赖项及其安全性的项
是的,我知道这需要更多的工作,但这是安全的方法。也许我已经找到了解决您问题的方法 如果在FlexBuilder3中使用自动生成的类,则可以捕获并修改传出的soap消息。在“Base[ServiceName]”类的“call()”函数中很容易做到这一点 您需要做的就是在字符串之前修改“soap”变量
message.body = soap.toString();
在我的例子中,我创建了cleanXML函数(见下文)。此函数删除所有等于“NaN”或具有xsi:nil='true'属性的XML元素
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();
我知道这个决定是不好的,因为在我的情况下,它是完美的