"Тип не ожидается", используя DataContractSerializer - но это просто класс, не смешные вещи?
Я рефакторинг своей XML-сериализации, и решил, что я попробую DataContractSerializer.
Все работает плавно, пока не потребуется сериализовать этот класс:
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;
}
}
}
}
Это дает мне следующее:
Введите "VDB_Sync.Model.Konstant" с именем контракта данных "Konstant: http://schemas.datacontract.org/2004/07/VDB_Sync.Model" не ожидается. Подумайте об использовании DataContractResolver или добавьте любые типы, не известные статически в список известных типов - например, с помощью атрибута KnownTypeAttribute или путем добавления их в список известных типов, переданных DataContractSerializer.
* Помощь, которую я нашел до сих пор, указывает на коллекции и типы. У меня есть enum (MySqlDbType) в моем классе, но получаю следующее: я даже получаю ту же ошибку, когда у меня нет данных, объявленных вообще: -x
Итак - что здесь происходит? Что мне не хватает?
для справки, так я сериализую его, VDB_SessionController является корнем: *
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();
}
Ответы
Ответ 1
Исключением, которое сообщается, является VDB_Sync.Model.Konstant. Это означает, что где-то дальше по цепочке этот класс втягивается в другой класс, и этот класс является сериализованным.
Проблема заключается в том, что в зависимости от того, как Konstant встроен в этот класс (например, если он находится в коллекции или в общем списке), DataContractSerializer может быть не подготовлен к его появлению во время десериализации.
Чтобы решить эту проблему, вам необходимо применить атрибут известного типа к классу, содержащему Konstant. Основываясь на вашем коде сериализации, я подозреваю, что это VDB_SessionController
.
Итак, попробуйте украсить этот класс атрибутом KnownType:
[KnownType(typeof(VDB_Sync.Model.Konstant)]
public class VDB_SessionController
Ответ 2
Добавьте это в 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);
Ссылка: 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
Ответ 3
Вы также можете объединить [KnownType]
и отражение, чтобы сделать ваш код более устойчивым к будущим изменениям.
[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;
}
}
Теперь DataContractSerializer
/DataContractJsonSerializer
/XmlSerializer
, настроенный для работы с Person
, также будет работать с любым типом, производным от Person
(пока он объявлен в той же сборке).
Ответ 4
используйте KnownTypeAttribute для разрешения класса DataFelt.
см. http://msdn.microsoft.com/en-us/library/system.runtime.serialization.knowntypeattribute.aspx
Ответ 5
Проблема для меня заключалась в том, что я возвращал интерфейс (IIndividual) из своего контроллера WebAPI. Когда я изменил этот тип возврата на тип класса (индивидуальный), эта ошибка исчезла.
Не работает:
[HttpGet]
[Route("api/v1/Individual/Get/{id}")]
public IIndividual Get([FromUri]int id)
{
return _individualService.Get(id);
}
В:
[HttpGet]
[Route("api/v1/Individual/Get/{id}")]
public Individual Get([FromUri]int id)
{
IIndividual individual = _individualService.Get(id);
return individual as Individual;
}
Ответ 6
Это похоже на предложенный @Leon, но с исправлением от @Bryan, "KnownTypeAttribute" должен быть в базовом классе, поэтому он должен выглядеть следующим образом:
[DataContract(Name="DataFelt")]
[KnownType(typeof(somenamespace.Konstant))]
public class DataFelt
и в подклассе:
[DataContract(Name="Konstant")]
public class Konstant : DataFelt
Ответ 7
Измените это:
[DataContract(Name="Konstant")]
public class Konstant : DataFelt
:
[DataContract(Name="Konstant")]
[KnownTypes(typeof(somenamespace.DataFelt))]
public class Konstant : DataFelt