簡體   English   中英

Silverlight WCF:將派生對象的集合用作基類的集合會導致NetDispatcherFaultException

[英]Silverlight WCF: consuming a collection of derived objects as a collection of base class results in a NetDispatcherFaultException

  1. 以下是Silverlight中的已知錯誤嗎?
  2. 如果是這樣,是否有任何好的解決方法?

類的層次結構很簡單:

在第一個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消息是“元素” http://schemas.datacontract.org/2004/07/XXX_BASE_CLASS ,其中包含“ http://schemas.datacontract.org/2004/07/XXX_DERIVED_CLASS ”數據協定的數據。 解串器不知道任何映射到該合同的類型。 將與“ DERIVED_CLASS”相對應的類型添加到已知類型的列表中-例如,通過使用KnownTypeAttribute屬性或將其添加到傳遞給DataContractSerializer的已知類型的列表中。 有關更多詳細信息,請參見InnerException。

[更新]當然會在客戶端引發錯誤。 服務器端會返回正確的值,但客戶端無法正確解析它們。 Fiddler說服務器返回了0個字節。 但實際上是客戶無法反序列化數據。

我需要一些方法來告訴運行時反序列化器如何將BaseClass反序列化為實際傳輸的類型。 [/更新]

您需要告訴DataContractSerializer將序列化的序列化為基類。 為此,您需要在派生類上使用Name屬性來闡明DataContract:

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

我100%不確定是否需要將Derived聲明為KnownType我強烈懷疑您這樣做。

另外,您正在Service類上使用KnownType-就我的理解,您應該在此處使用ServiceKnownType。 通常,您可以選擇:
一種。 在對象類上使用KnownType。
b。 在服務合同上使用ServiceKnownType(通常在服務的接口代理上)。
我喜歡后來的b。 因為它將所有KnownTypes集中在一個地方-一個。 讓他們在每個對象的所有代碼中進行分類-但這只是個人喜好。

如何在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上設置屬性,還是只在派生類型上設置屬性,還是在基類型上設置屬性。

這似乎是Silverlight /客戶端代碼生成器中的錯誤。

如果您有返回“基類”集合的服務,silverlight客戶端代碼生成器(添加服務引用)將無法將派生類型添加為ServiceKnownType / KnowType或在生成的客戶端代碼上添加任何內容。

我們當前使用的解決方案(直到我們完全放棄SL)是將ServiceKnownType聲明手動復制粘貼到所有派生類型的生成代碼中-每次生成代碼時。

真惡心! 但是有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM