"Type pas prévu", en utilisant DataContractSerializer - mais c'est juste une classe simple, pas de trucs drôles?

Je refactionne ma sérialisation XML, et j'ai pensé essayer le DataContractSerializer. Tout se déroule en douceur, jusqu'à ce qu'il ait besoin de sérialiser cette classe:

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

}
}

Il donne de moi:

Type 'VDB_Sync.Modèle.Konstant "with data contract name" Konstant: http: / / schemas.datacontract.org/2004/07/VDB_Sync.Modèle " n'est pas prévu. Envisagez d'utiliser un DataContractResolver ou ajouter des types non connus statiquement à la liste des types connus - par exemple, en utilisant l'attribut KnownTypeAttribute ou en les ajoutant à la liste des types connus passés à DataContractSerializer.

*L'aide que j'ai trouvé jusqu'à présent des points pour les collections et les Types. J'ai un enum (MySqlDbType) dans ma classe - mais j'obtiens ceci: j'obtiens même la même erreur quand je n'ai pas de DataMembers déclaré du tout: - x Ce qui se passe ici? Ce qui me manque?

pour la référence, c'est la façon dont je sérialisé, VDB_SessionController étant la racine:*

    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();
    }
49
demandé sur Julian 2012-01-10 00:15:59

7 réponses

l'exception qui est déclarée est pour VDB_Sync.Modèle.Konstant. Cela signifie que quelque part en haut de la chaîne, cette classe est tiré dans une autre classe et cette classe est celle qui est sérialisé.

le problème est que selon la façon dont Konstant est incorporé dans cette classe (par exemple, si elle est dans une collection ou une liste générique), le DataContractSerializer peut ne pas être préparé pour son apparition lors de la désérialisation.

à résolvez cela, vous devez appliquer l'attribut known-type à la classe qui contient Konstant. D'après votre code de sérialisation, je soupçonne que c'est VDB_SessionController .

alors, essayez de décorer cette classe avec l'attribut type connu:

[KnownType(typeof(VDB_Sync.Model.Konstant)]
public class VDB_SessionController
58
répondu competent_tech 2012-01-09 21:24:57

ajoutez ceci à 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);

référence: 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

15
répondu fenix2222 2015-01-30 10:45:57

vous pouvez également combiner [KnownType] et la réflexion pour rendre votre code plus résistant aux changements futurs.

[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 configuré pour fonctionner avec Person , fonctionnera également avec tout type dérivé de Person (tant qu'il est déclaré dans le même ensemble).

9
répondu dcastro 2017-10-18 12:52:23

utiliser KnownTypeAttribute pour résoudre la classe DataFelt. voir: http://msdn.microsoft.com/en-us/library/system.runtime.serialization.knowntypeattribute.aspx

4
répondu c0d1ng 2012-01-09 20:26:35

le problème pour moi était que je retournais L'Interface (Iindividu) de mon contrôleur WebAPI. Lorsque j'ai changé ce type de retour au type de classe (particulier), cette erreur a disparu.

ne travaillant pas:

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

    [HttpGet]
    [Route("api/v1/Individual/Get/{id}")]
    public Individual Get([FromUri]int id)
    {
        IIndividual individual = _individualService.Get(id);
        return individual as Individual;
    }
3
répondu Krishna 2016-11-15 18:56:26

c'est comme @Leon l'a suggéré, mais avec la correction de @Bryan, le 'KnownTypeAttribute' devrait être sur la classe de base, donc il devrait être comme ceci:

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

et dans la sous-classe:

[DataContract(Name="Konstant")]
public class Konstant : DataFelt
3
répondu Sohayb Hassoun 2017-10-18 12:52:04

Modifiez ce qui suit:

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

à ceci:

[DataContract(Name="Konstant")]
[KnownTypes(typeof(somenamespace.DataFelt))]
public class Konstant : DataFelt
0
répondu Leon 2012-01-09 20:39:49