«Тип не ожидается», используя DataContractSerializer – но это просто class, не смешные вещи?

Я рефакторинг моей XML-сериализации, и решил, что я попробую DataContractSerializer. Все работает плавно, пока не потребуется сериализовать этот 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; } } } } 

Это дает мне следующее:

Введите «VDB_Sync.Model.Konstant» с именем контракта с данными «Konstant: http: //schemas.datacontract.org/2004/07/VDB_Sync.Model» не ожидается. Подумайте об использовании DataContractResolver или добавьте любые типы, не известные статически в список известных типов – например, с помощью атрибута KnownTypeAttribute или путем добавления их в список известных типов, переданных DataContractSerializer.

* Помощь, которую я нашел до сих пор, указывает на коллекции и типы. У меня есть enum (MySqlDbType) в моем classе, но получаю следующее: я даже получаю ту же ошибку, когда у меня нет объявленных DataMembers: -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(); } 

Сообщается об исключении для VDB_Sync.Model.Konstant. Это означает, что где-то дальше по цепочке этот class втягивается в другой class, и этот class является сериализованным.

Проблема в том, что в зависимости от того, как Konstant встроен в этот class (например, если он находится в коллекции или общем списке), DataContractSerializer может быть не подготовлен к его появлению во время десериализации.

Чтобы решить эту проблему, вам необходимо применить атрибут известного типа к classу, который содержит Konstant. Основываясь на вашем коде сериализации, я подозреваю, что это VDB_SessionController .

Итак, попробуйте украсить этот class атрибутом KnownType:

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

Добавьте это в 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- -реакция тела в обмен на содержание и форум = ФОС

Вы также можете комбинировать [KnownType] и reflection, чтобы сделать ваш код более устойчивым к будущим изменениям.

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

Теперь DataContractSerializer / DataContractJsonSerializer / XmlSerializer настроенный для работы с Person , также будет работать с любым типом, производным от Person (если он объявлен в той же сборке).

используйте KnownTypeAttribute для разрешения classа DataFelt. см .: http://msdn.microsoft.com/en-us/library/system.runtime.serialization.knowntypeattribute.aspx

Проблема для меня заключалась в том, что я возвращал интерфейс (II индивидуал) из своего controllerа WebAPI. Когда я изменил этот тип возврата на тип classа (индивидуальный), эта ошибка исчезла.

Не работает:

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

Это похоже на предложение @Leon, но с исправлением от @Bryan, «KnownTypeAttribute» должен быть в базовом classе, поэтому он должен выглядеть следующим образом:

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

и в подclassе:

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

Измените это:

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

к этому:

 [DataContract(Name="Konstant")] [KnownTypes(typeof(somenamespace.DataFelt))] public class Konstant : DataFelt 
  • Каков наилучший способ анализа (большого) XML в коде C #?
  • Давайте будем гением компьютера.