我们正在开发一个带有Flex前端和C#后端的应用程序,通过Web服务连接。 我们使用FLex Builder 3的Web服务管理器来自动生成Web服务类。 当Flex序列化我们的对象时,问题是,例如,当我们有一个没有值的Number属性时,这被序列化为NaN,而我们的后端不知道NaN。另一个例子是当我们序列化循环引用时,我们得到一个堆栈溢出异常。 我知道在java中,例如,你可以配置xstream使用循环引用的方式......所以,问题是,我们可以改变Flex序列化对象的方式,这样C#可以使用这个前端吗?关于flex序列化对象有什么问题我们应该知道吗? 谢谢! 乔治
答案 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)
我不知道如何更改自动生成的类的序列化,但我会尝试在下面提供一些帮助:
你可能正在寻找什么(虽然我从来没有使用过这个,但我只是看到它一直提到):
我做过的事情:
我从未尝试过的另一个想法:
关于你面临的问题:
答案 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();
我知道这个决定并不好,在我的情况下它完美无缺!