2

I am using .net Core 1.1 and writing a console application. I need to Serialize an Object with some basic properties of strings and int as well as some IEnumerable Objects and serialize it as XML so I can save it to a "data.xml" file.

I receive the Exception: System.Runtime.Serialization.SerializationException: 'Type 'System.Collections.Generic.List`1[[CorpsDataExtractor.ViewModels.LegacyView, CorpsDataExtractor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' with data contract name 'ArrayOfLegacyView:http://schemas.datacontract.org/2004/07/CorpsDataExtractor.ViewModels' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'

I currently am able to serialize my Object as JSON, but am having trouble utilizing the DataContractSerializer. I Added the Known Type List that the exception states I am missing but it still fails.

// This List isretrieved using Entity Framework Core
      List<LegacyView> legacyData = await _corpsRepo.ListLegacyData();

// The Below Line will write to a JSON File. No Error and works
        File.WriteAllText(@"E:\\CorporationsDataLegacy.json", JsonConvert.SerializeObject(legacyData));

// This Creates a Known Type List for the DataContractSerializer
        var knownTypeList = new List<Type>
        {
            typeof(LegacyView),
            typeof(People),
            typeof(DocumentType)
        };

        FileStream writer = new FileStream(@"E:\\data.xml", FileMode.Create);
        var ser = new DataContractSerializer(typeof(LegacyView), knownTypeList );
// When Debugging I Receive The stated exception at this line
        ser.WriteObject(writer, legacyData);

Below Are my Class ViewModels:

Legacy View

[DataContract]
public class LegacyView
{
    [DataMember]
    public string Ubi { get; set; }
    [DataMember]
    public IEnumerable<Person> People{ get; set; }
    [DataMember]
    public IEnumerable<DocumentType> DocumentTypes { get; set; }
}

Person

[DataContract]
public class Person
{ 
    [DataMember]
    public string FirstName { get; set; }
    [DataMember]
    public string MiddleName { get; set; }
}

Documents

[DataContract]
public class DocumentType
{ 
    [DataMember]
    public string Document { get; set; }
    [DataMember]
    public DateTime? CompletedDate { get; set; }
}

Any Direction on what I am missing?

Scornwell
  • 597
  • 4
  • 19
  • Have you tried to add `typeof(IEnumerable), typeof(IEnumerable)` to the known types? – Gusman Jun 08 '17 at 22:37
  • @Gusman, using a combination of your answer and answer worked, I left my properties as IEnumerable but where I declared my KnownType List I needed to make those Concrete by using List – Scornwell Jun 08 '17 at 23:00
  • Glad you got it working. Add your solution as an answer as this can help others with your same problem. – Gusman Jun 08 '17 at 23:00

2 Answers2

1

I might be a bit off as I've done more of XmlSerialize rather than DataContracts one, but I believe both assume eventual deserialization of the content. And with IEnumerable<T> as the type, deserializer wouldn't know what class to actually instantiate to back the interface during deserialization. Change fields to concrete classes instead of enumeration, and that should work.

LB2
  • 4,802
  • 19
  • 35
  • I appreciate your input. I changed them to concrete classes and still received that same error. I am going to add the Known Type Attribute and see if that fixes it, although the error states I can use the Known Type List. – Scornwell Jun 08 '17 at 22:44
  • Although I didn't need to change the [Datamember] to a concrete class, but I did need to change the Known Type List to a Concrete Class So the answer was a combination between you and Gusman – Scornwell Jun 08 '17 at 23:01
1

By using a Both Gusman and LB2 comments I was able to solve the issue. As LB2 states "with IEnumerable as the type, deserializer wouldn't know what class to actually instantiate to back the interface during deserialization."

This is why the error was occurring, however the problem did not exist at the Class LegacyView [DataMember] level, it existed at the known Types that were being passed into the DataContractSerializer.

Gusman was correct that I needed to tell the DataContractSerializer that these were going to be an enumerable type.

// I needed to tell the DataContractSerializer what the types were
    var knownTypeList = new List<Type>
    {
        typeof(List<LegacyView>),
        typeof(List<People>),
        typeof(List<DocumentType>)
    };

    using (var writer = new FileStream(@"E:\\myTestExample.xml", FileMode.Create)) 
    {
        var ser = new DataContractSerializer(typeof(LegacyView), knownTypeList);
        ser.WriteObject(writer, legacyData);
    }
Community
  • 1
  • 1
Scornwell
  • 597
  • 4
  • 19