"Type not expected", using DataContractSerializer - but it's just a simple class, no funny stuff?

.NetXmlSerializationXml SerializationDatacontractserializer

.Net Problem Overview


I'm refactoring my XML-serialization, and figured I'd try the DataContractSerializer. Everything runs smoothly, until it needs to serialize this class:

using System;
using System.Runtime.Serialization;

namespace VDB_Sync.Model
{
[DataContract(Name="Konstant")]
public class Konstant : DataFelt
{
    [DataMember]
    private MySqlDbType mydataType;
    [DataMember]
    private object value;

    public Konstant(string navn, MySqlDbType dataType, object value)
        : base(navn, dataType, "*Konstant", false, false)
    {
        //this.navn = navn;
        this.mydataType = dataType;
        this.value = value;

        if (navn.Contains("*Løbenummer"))
        {
            navn = "*Konstant: " + Convert.ToString(value);
        }
    }

    public object Value
    {
        get
        {
            return value;
        }
    }

}
}

It give's me this:

> Type 'VDB_Sync.Model.Konstant' with data contract name 'Konstant:http://schemas.datacontract.org/2004/07/VDB_Sync.Model'; is not expected. Consider using a DataContractResolver or 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.

*The help I've found so far points to collections and Types. I do have an enum (MySqlDbType) in my class - but get this: I even get the same error when i have no DataMembers declared at all :-x So - what's going on here? What am I missing?

for reference, this is how i serialized it, VDB_SessionController being the root:*

    public void GemKonfig(VDB_SessionController session)
    {
        var settings = new XmlWriterSettings()
        {
            Indent = true,
            IndentChars = "\t"
        };

        var writer = XmlWriter.Create(defaultFile, settings);
        DataContractSerializer ser =
            new DataContractSerializer(typeof(VDB_SessionController));

        ser.WriteObject(writer, session);
        writer.Close();
    }

.Net Solutions


Solution 1 - .Net

The exception that is being reported is for VDB_Sync.Model.Konstant. This means that somewhere further up the chain, this class is being pulled into another class and that class is the one being serialized.

The issue is that depending on how Konstant is embedded in this class (for example, if it is in a collection or a generic list), the DataContractSerializer may not be prepared for its appearance during deserialization.

To resolve this, you need to apply the known-type attribute to the class that contains Konstant. Based on your serialization code, I suspect that this is VDB_SessionController.

So, try decorating this class with the KnownType attribute:

[KnownType(typeof(VDB_Sync.Model.Konstant)]
public class VDB_SessionController

Solution 2 - .Net

Add this to WebApiConfig.cs

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;

var json = config.Formatters.JsonFormatter;

json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);

Reference: http://www.datazx.cn/Forums/en-US/a5adf07b-e622-4a12-872d-40c753417645/action?threadDisplayName=web-api-error-the-objectcontent1-type-failed-to-serialize-the-response-body-for-content&forum=wcf

Solution 3 - .Net

You can also combine [KnownType] and reflection to make your code more resistant to future changes.

[DataContract]
[KnownType("GetKnownPersonTypes")]
internal class Person
{
    private static IEnumerable<Type> _personTypes;

    private static IEnumerable<Type> GetKnownTypes()
    {
        if (_personTypes == null)
            _personTypes = Assembly.GetExecutingAssembly()
                                    .GetTypes()
                                    .Where(t => typeof (Person).IsAssignableFrom(t))
                                    .ToList();
        return _personTypes;
    }
}

Now a DataContractSerializer / DataContractJsonSerializer / XmlSerializer configured to work with Person, will also work with any type derived from Person (as long as it's declared within the same assembly).

Solution 4 - .Net

Solution 5 - .Net

The problem for me was that I was returning the Interface (IIndividual) from my WebAPI controller. When I changed that return type to the Class (Individual) type, this error went away.

Not working:

    [HttpGet]
    [Route("api/v1/Individual/Get/{id}")]
    public IIndividual Get([FromUri]int id)
    {
        return _individualService.Get(id);
    }

Working:

    [HttpGet]
    [Route("api/v1/Individual/Get/{id}")]
    public Individual Get([FromUri]int id)
    {
        IIndividual individual = _individualService.Get(id);
        return individual as Individual;
    }

Solution 6 - .Net

It is like as @Leon suggested but with the fix from @Bryan, the 'KnownTypeAttribute' should be on the base class, so it should be like this:

[DataContract(Name="DataFelt")]
[KnownType(typeof(somenamespace.Konstant))]
public class DataFelt

and in the Subclass:

[DataContract(Name="Konstant")]
public class Konstant : DataFelt

Solution 7 - .Net

Change this:

[DataContract(Name="Konstant")]
public class Konstant : DataFelt

to this:

[DataContract(Name="Konstant")]
[KnownTypes(typeof(somenamespace.DataFelt))]
public class Konstant : DataFelt

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJulianView Question on Stackoverflow
Solution 1 - .Netcompetent_techView Answer on Stackoverflow
Solution 2 - .Netfenix2222View Answer on Stackoverflow
Solution 3 - .NetdcastroView Answer on Stackoverflow
Solution 4 - .NetgethomastView Answer on Stackoverflow
Solution 5 - .NetfluidguidView Answer on Stackoverflow
Solution 6 - .NetSohayb HassounView Answer on Stackoverflow
Solution 7 - .NetLeonView Answer on Stackoverflow