#wcf #apache-flex #object #soap #flash-builder
#wcf #apache-flex #объект #soap #flash-builder
Вопрос:
На сервере настроена служба wcf, которая поставляет данные в проект flex, созданный с использованием Flashbuilder4. Я использовал функцию самоанализа веб-сервиса для генерации DTO и служебных прокси. Один из DTO имеет свойство типа Object. Содержимое этого универсального объекта будет меняться в зависимости от определенных условий, но всегда будет другим сложным объектом. Создание и заполнение vo в FB4 проходит гладко, но когда объект сериализуется, он выглядит следующим образом:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<tns:GetC xmlns:tns="EP2ProblemDemo1">
<tns:anyObj>
<tns:Property1>yo!</tns:Property1>
<tns:Property2>yo! yo!</tns:Property2>
</tns:anyObj>
</tns:GetC>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Где вы можете заметить, что в свойстве anyObj отсутствует какая-либо информация о типе, несмотря на ссылку на объект типа ClassB:
public class ClassA
{
public string Property1;
}
public class ClassB : ClassA
{
public string Property2;
}
В аргументе anyObj для GetC отсутствует что-то вроде следующего:
xsi:type=»tns:ClassB» xmlns:tns=»EP2ProblemDemo1″
Что, в свою очередь, выдает ошибку, когда служба wcf пытается декодировать сообщение. Я думаю, что служба интерпретирует содержимое anyObj как массив, который не может быть неявно преобразован в базовый объект?
При установке аргумента anyObj (типа Object) экземпляру ClassB кажется, что информация о типе теряется. Правильное ли это поведение? У меня создалось впечатление, что даже если вы можете установить переменную суперкласса для ссылки на один из его подклассов, информация о типе подкласса должна быть сохранена и, следовательно, также включена в сериализованное представление этого объекта.
РЕДАКТИРОВАТЬ Похоже, что сериализатор FlashBuilder4 удаляет информацию о конкретном типе и пространстве имен из свойства типа Object при отправке обратно в службу wcf, которая затем не может десериализовать то, что выглядит как массив. Кроме того, при импорте файла WSDL в FB4 наследование VO теряется, поскольку они в конечном итоге расширяют EventDispatcher, чтобы сделать его доступным для привязки.
РЕШЕНИЕ Моим решением было изменить тактику и перейти к удаленному взаимодействию с AMF, реализованному в .NET с использованием FluorineFx,официального веб-сайта FluorineFx, который прекрасно работает и имеет приятный побочный эффект снижения потребления полосы пропускания из-за передачи данных в виде массива байтов.
Я полагаю, что WebORB,официальный сайтWebORB, также можно использовать для реализации AMF в .net, но я еще не пробовал.
Ответ №1:
Вы не можете использовать «любой» объект. Вы всегда должны явно описывать, какие типы разрешены. Проверьте KnownTypeAttribute и ServiceKnownTypeAttribute или DataContractResolver (у меня пока нет слишком большого опыта работы с этим). Если вам действительно нужно отправить произвольные данные и вы не можете заранее определить все возможные объекты, используйте вместо этого XElement. В xsd это будет описано как xsd: any.
Комментарии:
1. Ах да! я пропустил это в демонстрации проблемы, но, к сожалению, не в реальном проекте.
Ответ №2:
-
Для всех типов объектов, которые вы отправляете по сети, вам необходимо установить атрибут с именем [DataContract]
[DataContract] открытый класс ClassA { свойство общедоступной строки 1; }
-
Вместо использования базового типа (object) вам следует использовать базовый класс и использовать атрибут [KnownType]
[ServiceContract(пространство имен = «EP2ProblemDemo1»)] общедоступный интерфейс IService { [OperationContract] ClassC GetC(ClassD ClassB); }
[KnownType(typeof(ClassA)), KnownType(typeof(ClassB))] открытый класс ClassD { }
Надеюсь, это поможет
Комментарии:
1. Спасибо за быстрый ответ! Похоже, я собрал довольно плохую демонстрацию, поскольку эти пункты действительны и реализованы в реальном проекте.