“Escriba no esperado”, usando DataContractSerializer, pero es solo una clase simple, ¿no hay cosas divertidas?

Estoy refactorizando mi serialización XML, y pensé que probaría el DataContractSerializer. Todo funciona sin problemas, hasta que necesite serializar esta clase:

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; } } } } 

Me da esto:

Escriba ‘VDB_Sync.Model.Konstant’ con el nombre del contrato de datos ‘Konstant: http: //schemas.datacontract.org/2004/07/VDB_Sync.Model’ no se espera. Considere el uso de un DataContractResolver o agregue cualquier tipo no conocido de forma estática a la lista de tipos conocidos, por ejemplo, utilizando el atributo KnownTypeAttribute o agregándolos a la lista de tipos conocidos pasados ​​a DataContractSerializer.

* La ayuda que he encontrado hasta ahora apunta a colecciones y tipos. Tengo una enumeración (MySqlDbType) en mi clase, pero entérate: incluso recibo el mismo error cuando no tengo ningún DataMembers declarado: -x Entonces, ¿qué está pasando aquí? ¿Qué me estoy perdiendo?

como referencia, así es como lo serialé, siendo VDB_SessionController la raíz: *

  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(); } 

La excepción que se informa es para VDB_Sync.Model.Konstant. Esto significa que en algún lugar más arriba de la cadena, esta clase está siendo arrastrada a otra clase y esa clase es la que está siendo serializada.

El problema es que, dependiendo de cómo esté integrado Konstant en esta clase (por ejemplo, si está en una colección o en una lista genérica), es posible que el DataContractSerializer no esté preparado para su aparición durante la deserialización.

Para resolver esto, debe aplicar el atributo de tipo conocido a la clase que contiene Konstant. Basado en su código de serialización, sospecho que este es VDB_SessionController .

Por lo tanto, intente decorar esta clase con el atributo KnownType:

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

Agregue esto a 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); 

Referencia: 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

También puede combinar [KnownType] y la reflexión para que su código sea más resistente a los cambios futuros.

 [DataContract] [KnownType("GetKnownPersonTypes")] internal class Person { private static IEnumerable _personTypes; private static IEnumerable GetKnownTypes() { if (_personTypes == null) _personTypes = Assembly.GetExecutingAssembly() .GetTypes() .Where(t => typeof (Person).IsAssignableFrom(t)) .ToList(); return _personTypes; } } 

Ahora un DataContractSerializer / DataContractJsonSerializer / XmlSerializer configurado para trabajar con Person , también funcionará con cualquier tipo derivado de Person (siempre que se declare dentro del mismo ensamblado).

utilice KnownTypeAttribute para resolver la clase DataFelt. ver: http://msdn.microsoft.com/en-us/library/system.runtime.serialization.knowntypeattribute.aspx

El problema para mí fue que estaba devolviendo la interfaz (IIindividual) desde mi controlador WebAPI. Cuando cambié ese tipo de devolución al tipo Clase (Individual), este error desapareció.

No funciona:

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

Trabajando:

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

Es como lo sugirió @Leon, pero con la solución de @Bryan, el ‘KnownTypeAttribute’ debería estar en la clase base, por lo que debería ser así:

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

y en la Subclase:

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

Cambia esto:

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

a esto:

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