wcf - 如何在 WCF 中接受基类型的集合

标签 wcf inheritance soap collections wsdl

设置

我有一个 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 消息中,Animals 集合包含一个基本 Animal 类型的实例、一个派生的 Tiger 类型的实例和一个派生的 Bear 类型的实例。 WCF 应该能够成功反序列化此消息。

问题

WCF收到上述消息时不会抛出任何异常。相反,它只是完全忽略派生类型(Tiger 和 Bear),并且当反序列化消息传递到我的代码时,Animals 集合仅包含 Crocodile 条目,因为它是基本类型。

所以,我想我有两个问题...首先,为什么 WCF 不反序列化集合中的派生类型实例。其次,既然 WCF 显然不喜欢这个 SOAP 消息的某些内容,为什么它不抛出异常呢?这种无声的失败非常令人不安。

最佳答案

好的...我解决了问题。事实证明,此场景的 SOAP 语法需要一些额外的工作才能正确。由于 Animals 集合被定义为 Animal 类型的数组,因此 SOAP 消息中的所有子元素都必须是元素,即使它们实际上是派生类型的实例。实际的实例类型由“type”属性定义,该属性是 XMLSchema-instance 命名空间的一部分。因此,我的 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 消息,它应该抛出异常。它不应该只是默默地忽略消息的一部分!

关于wcf - 如何在 WCF 中接受基类型的集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1295357/

相关文章:

c# - WP7 推送通知服务器设置

c - 无法在 xml 中获取 Soap 响应的根节点

java - 如何从返回 dataset(<Object> any) 的 Web 服务创建 POJO

wcf - 如何模拟 WCF 服务的用户?

托管在 IIS6 上的 WCF

c# - 如何将 WCF 配置为仅签署 TimeStamp header

python - python 3中的简单方法继承

c++ - 奇怪的重复模板模式 : double inheritance

C++继承问题

php - 网站需要永远加载然后我得到 "Uncaught SoapFault exception"