2009-08-18 2 views
2

установки параметровКак принимать коллекцию базового типа в WCF

У меня есть службы WCF, который предоставляет базовый тип (например, животных), а также несколько производных типов (например, лев, тигр, и Медведь). Другой тип (например, Zoo) включает свойство, которое представляет собой набор базового типа. Основной тип - бетон, не аннотация, поэтому вполне приемлемо для коллекции содержать экземпляры базового типа и/или производные типы (в любой комбинации). Например:

[DataContract, KnownType(typeof(Lion)), 
KnownType(typeof(Tiger)), KnownType(typeof(Bear))] 
public class Animal 
{ 
    [DataMember] 
    public string Species { get; set; } 
} 

[DataContract] 
public class Lion : Animal { } 


[DataContract] 
public class Tiger : Animal { } 


[DataContract] 
public class Bear : Animal { } 

[DataContract] 
public class Zoo 
{ 
    [DataMember] 
    public List<Animal> Animals { get; set; } 
} 

Один из моих операций обслуживания принимает этот тип в качестве параметра, например так:

[ServiceContract] 
public interface IZooService 
{ 
    [OperationContract] 
    void SetZoo(Zoo zoo); 
} 

Все это хорошо, и излучаемый WSDL выглядит прекрасно для меня. Он содержит все типы и правильно указывает, что производные типы наследуются от базового типа. Таким образом, я должен быть в состоянии назвать свою службу, используя сообщение SOAP, таких как:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:z="http://zoo.org"> 
    <soapenv:Header/> 
    <soapenv:Body> 
     <z:SetZoo> 
     <z:Zoo> 
      <z:Animals> 
       <z:Animal> 
        <z:Species>Crocodile</z:Species> 
       </z:Animal> 
       <z:Tiger> 
        <z:Species>Bengal</z:Species> 
       </z:Tiger> 
       <z:Bear> 
        <z:Species>Grizzly</z:Species> 
       </z:Bear> 
      </z:Animals> 
     </z:Zoo> 
     </z:SetZoo> 
    </soapenv:Body> 
</soapenv:Envelope> 

В приведенном выше сообщении SOAP, коллекция животных содержит один экземпляр базового типа Animal, экземпляр производного Tiger тип и экземпляр производного типа Bear. WCF должен иметь возможность десериализовать это сообщение успешно.

Проблема

WCF не выбрасывает никаких исключений, когда он получает сообщение выше. Вместо этого он просто полностью игнорирует производные типы (Tiger and Bear), и к тому времени, когда десериализованное сообщение передается моему коду, коллекция Animals содержит только запись Crocodile, так как она имеет базовый тип.

Итак, у меня есть два вопроса ... Во-первых, почему WCF не десериализует экземпляры производного типа в коллекции. И, во-вторых, поскольку WCF явно не нравится что-то в этом сообщении SOAP, почему он не бросает исключение? Такая тихая неудача очень беспокоит.

ответ

6

Хорошо, я понял, что проблема. Оказывается, синтаксис SOAP для этого сценария требует немного дополнительной работы, чтобы получить право. Поскольку коллекция Animals определена как массив типов Animal, все дочерние элементы в SOAP-сообщении должны быть элементами, даже если они являются фактически экземплярами производного типа. Фактический тип экземпляра определяется атрибутом «type», который является частью пространства имен XMLSchema-экземпляра. Итак, мой SOAP сообщение должно бы выглядеть следующим образом:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://zoo.org"> 
<soapenv:Header/> 
<soapenv:Body> 
    <z:SetZoo> 
    <z:Zoo> 
     <z:Animals> 
      <z:Animal> 
       <z:Species>Crocodile</z:Species> 
      </z:Animal> 
      <z:Animal i:type="z:Tiger"> 
       <z:Species>Bengal</z:Species> 
      </z:Animal> 
      <z:Animal i:type="z:Bear"> 
       <z:Species>Grizzly</z:Species> 
      </z:Animal> 
     </z:Animals> 
    </z:Zoo> 
    </z:SetZoo> 
</soapenv:Body> 
</soapenv:Envelope> 

Конечно, это еще не решает мою другую озабоченность, которая является то, что WCF десериализатор должен бросить исключение, если он не понимает сообщение SOAP , Он не должен просто игнорировать части сообщения!

+0

Отлично, спасибо! Я чуть не взорвался, пытаясь создать правильное сообщение с мыльным UI ... – juarola

+0

Я думаю, что десериализатор WCF, не игнорирующий части сообщения, является неприятным. Это заставит вас всегда держать клиента и сервер в блокировке, не обязательно желаемой чертой. – Jeff

Смежные вопросы