Silverlight WCF:在NetDispatcherFaultException中使用派生对象的集合作为基类的集合

时间:2015-08-19 12:35:43

标签: c# wcf silverlight datacontractserializer

  1. 以下是Silverlight中的已知错误?
  2. 如果是的话,有什么好的解决方法吗?
  3. 类层次结构很简单:

    第一个PCL上的

    namespace ClassLibrary1
    {
        [DataContract]
        public class BaseClass
        {
            [DataMember]
            public string BaseString { get; set; }
        }
    }
    

    在第二个PCL上(当然,引用第一个......)

    namespace ClassLibrary2
    {
        [DataContract]
        public class Derived : BaseClass
        {
            [DataMember]
            public string DerivedString { get; set; }
        }
    }
    

    服务(在WebApp上):

    namespace SilverlightApplication1.Web
    {
        [ServiceContract(Namespace = "")]
        [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
        [KnownType(typeof(Derived))]
        public class Service1
        {
            [OperationContract]
            public List<BaseClass> GetSomething()
            {
                var data = new List<BaseClass>();
                data.Add(new Derived());
                return data;
            }
    
        }
    }
    

    现在, 服务引用不会将ServiceKnownType属性添加到reference.cs文件中。以及由此产生的错误:

      

    格式化程序在尝试反序列化消息时抛出异常:尝试反序列化参数时出错:GetQueueItemsResult。 InnerException消息是&#39;元素&#39; http://schemas.datacontract.org/2004/07/XXX_BASE_CLASS&#39;包含&#39; http://schemas.datacontract.org/2004/07/XXX_DERIVED_CLASS&#39;的数据。数据合同。反序列化器不知道映射到此合同的任何类型。添加与&#39; DERIVED_CLASS&#39;对应的类型到已知类型列表 - 例如,通过使用KnownTypeAttribute属性或将其添加到传递给DataContractSerializer的已知类型列表。&#39;。有关详细信息,请参阅InnerException。

    [增订] 当然,错误是在客户端上引发的。服务器端返回正确的值,客户端无法正确解析它们。 Fiddler说服务器返回0字节。 但实际上,客户端无法反序列化数据。

    我需要一些方法告诉运行时反序列化器如何将BaseClass反序列化为实际传输的类型。 [/更新]

3 个答案:

答案 0 :(得分:1)

您需要告诉DataContractSerializer将派生序列化为基类。为此,您需要在派生类上使用Name属性阐明DataContract:

[DataContract(Name="BaseClass")]
public class Derived : BaseClass 
    [DataMember]
    public string DerivedString { get; set; }
}

我100%不确定您是否需要将Derived声明为KnownType - 我强烈反对您这样做。

此外,您在Service类上使用了KnownType - 我的理解是您应该在这里使用ServiceKnownType。一般来说,您可以选择:
一个。在对象类上使用KnownType 湾在服务合同上使用ServiceKnownType(通常在服务的接口扩展上) 我更喜欢后来的b。因为它将所有KnownTypes分组在一个地方 - 作为一个地方。让他们在每个对象的代码上进行搜索 - 但这只是个人偏好。

答案 1 :(得分:0)

如何在DataContract类型定义中设置KnownType属性,使反序列化器能够在运行时找到正确的类型,它是否解决了这个问题?

namespace ClassLibrary1
{
    [DataContract]
    [KnownType(typeof(BaseClass))]
    [KnownType(typeof(Derived))]
    public class BaseClass
    {
        [DataMember]
        public string BaseString { get; set; }
    }
}
namespace ClassLibrary2
{
    [DataContract]
    [KnownType(typeof(BaseClass))]
    [KnownType(typeof(Derived))]
    public class Derived : BaseClass
    {
        [DataMember]
        public string DerivedString { get; set; }
    }
}

说实话,我不确定您是要在DataContracts上设置属性还是仅在派生类型中设置属性,或仅在basetype上设置属性。

答案 2 :(得分:0)

这似乎是Silverlight /客户端代码生成器中的一个错误。

如果你有一个服务返回&#34;基类&#34; silverlight客户端代码生成器(添加服务引用)将无法将派生类型添加为ServiceKnownType / KnowType或生成的客户端代码上的任何内容。

我们当前使用的解决方案(直到我们完全放弃SL)是每次生成代码时,手动将ServiceKnownType声明复制粘贴到所有派生类型的生成代码中。

恶心!但是有效。