Search code examples
c#wcfsilverlightdatacontractserializer

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


  1. is the following a known bug in Silverlight?
  2. if so, are there any good workarounds?

the class hierarchy is simple:

on the first PCL:

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

on the second PCL (of course, referencing the first...)

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

the service (on the 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;
        }

    }
}

Now, the service reference does not add the ServiceKnownType attribute to the reference.cs file. and the resulting error:

The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter :GetQueueItemsResult. The InnerException message was 'Element 'http://schemas.datacontract.org/2004/07/XXX_BASE_CLASS' contains data of the 'http://schemas.datacontract.org/2004/07/XXX_DERIVED_CLASS' data contract. The deserializer has no knowledge of any type that maps to this contract. Add the type corresponding to 'DERIVED_CLASS' to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details.

[UPDATED] the error is thrown on the client, of course. the server side returns the correct values, bu the client cannot parse them properly. Fiddler says the server returned 0 bytes. but in reality it's the client who fails to deserialize the data.

I need some way to tell the runtime deserializer how to deserialize the BaseClass into the actual type transferred. [/UPDATED]


Solution

  • This seems to be a bug in Silverlight/client code generator.

    if you have a service returning a collection of "base class" the silverlight client code generator (add service reference) will not be able to add the derived types as ServiceKnownType / KnowType or whatever on the generated client code.

    the solution we are currently using (until we abandon SL altogether) is to manually copy-paste the ServiceKnownType declarations into the generated code for all derived type - every time we generate the code.

    disgusting! but works.