«Тип не ожидается», используя DataContractSerializer - но это просто простой класс, ничего смешного? - PullRequest
54 голосов
/ 10 января 2012

Я рефакторинг своей 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) в моем классе - но получаю это: я даже получаю ту же ошибку, когда у меня вообще нет объявленных 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();
    }

Ответы [ 7 ]

63 голосов
/ 10 января 2012

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

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

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

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

[KnownType(typeof(VDB_Sync.Model.Konstant)]
public class VDB_SessionController
15 голосов
/ 26 мая 2014

Добавить это в 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

13 голосов
/ 23 марта 2014

Вы также можете комбинировать [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 голосов
/ 15 ноября 2016

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

Не работает:

    [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;
    }
4 голосов
/ 10 января 2012

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

3 голосов
/ 21 октября 2015

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

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

и в подклассе:

[DataContract(Name="Konstant")]
public class Konstant : DataFelt
0 голосов
/ 10 января 2012

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

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

на это:

[DataContract(Name="Konstant")]
[KnownTypes(typeof(somenamespace.DataFelt))]
public class Konstant : DataFelt
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...