2009-08-18 70 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消息中,动物集合包含底座动物类型的一个实例,派生虎的一个实例类型以及派生Bear类型的实例。 WCF应该能够成功地反序列化此消息。

当它接收到上述消息的问题

WCF不会引发任何异常。相反,它完全忽略派生类型(Tiger和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> 

当然,这还是如果它不理解SOAP消息并没有解决我的其他的关注,这就是WCF解串器应该抛出一个异常。它不应该默默地忽略部分信息!

+0

非常好,谢谢!我几乎崩溃试图用肥皂用户界面创建一个适当的消息... – juarola 2012-03-04 12:27:21

+0

我认为WCF解串器不会忽略部分消息是麻烦的。这会迫使你始终保持客户端和服务器的同步,而不一定是一个理想的特性。 – Jeff 2012-12-11 18:20:55

相关问题