Sérialisation .NET WebAPI k_BackingField Nastiness

86

Lorsque je sérialise les éléments suivants:

[Serializable]
public class Error
{

    public string Status { get; set; }
    public string Message { get; set; }
    public string ErrorReferenceCode { get; set; }
    public List<FriendlyError> Errors { get; set; }
}

Je reçois ce désordre dégoûtant:

<ErrorRootOfstring xmlns:i="http://www.w3.org/2001/XMLSchema-instance"   xmlns="http://schemas.datacontract.org/2004/07/Printmee.Api">
<_x003C_Errors_x003E_k__BackingField>
An exception has occurred. Please contact printmee support
</_x003C_Errors_x003E_k__BackingField>
<_x003C_LookupCode_x003E_k__BackingField>988232ec-6bc9-48f3-8116-7ff7c71302dd</_x003C_LookupCode_x003E_k__BackingField>
</ErrorRootOfstring>

Ce qui donne? Comment puis-je rendre ça joli? Les réponses JSON contiennent également le k_BackingField

Michée
la source
Cela m'a aidé: stackoverflow.com/questions/15388452/…
granadaCoder

Réponses:

126

Par défaut, vous n'avez pas besoin d'utiliser [Serializable]ni [DataContract]de travailler avec l'API Web.

Laissez simplement votre modèle tel quel, et l'API Web sérialiserait toutes les propriétés publiques pour vous.

Seulement si vous souhaitez avoir plus de contrôle sur ce qui est inclus, vous décorez ensuite votre classe avec [DataContract]et les propriétés à inclure [DataMember](car DCS et JSON.NET respectent ces attributs).

Si pour une raison quelconque, vous avez besoin du [Serializable]sur votre classe (c'est-à-dire que vous la sérialisez dans un flux mémoire pour une raison quelconque, faites des copies approfondies, etc.), vous devez utiliser les deux attributs conjointement pour éviter les noms de champ de sauvegarde:

[Serializable]
[DataContract]
public class Error
{
    [DataMember]
    public string Status { get; set; }
    [DataMember]
    public string Message { get; set; }
    [DataMember]
    public string ErrorReferenceCode { get; set; }
    [DataMember]
    public List<FriendlyError> Errors { get; set; }
}
Filip W
la source
6
C'était tout - j'avais juste besoin de supprimer le [Serializable]. Merci.
Micah
Merci Filip, dois garder les attributs à cause du cache .. BTW, je suis un grand fan de votre blog .. continuez à venir!
Stephen Patten
20
C'est tout simplement terrible. Pourquoi Microsoft ne peut JAMAIS rien faire de correct en matière de sérialisation?
Chris Marisic
Il existe une solution plus générale, comme je le montre dans ma propre réponse ci-dessous.
JotaBe
Peut-être que le problème avec la sérialisation est la définition de «correct», chacun a besoin de données à sa manière.
Luiz Felipe
94

Il existe une solution plus générale: vous pouvez configurer le sérialiseur Json pour ignorer l' [Serializable]attribut, afin de ne pas avoir à modifier les attributs de vos classes.

Vous devez effectuer ce changement de configuration au démarrage de l'application, c'est-à-dire dans l' Application_Startévénement Global.asax :

var serializerSettings =
  GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings;
var contractResolver =
  (DefaultContractResolver)serializerSettings.ContractResolver;
contractResolver.IgnoreSerializableAttribute = true;

Vous pouvez également apporter d'autres modifications à la sérialisation Json, comme la spécification de formats pour la sérialisation des dates, et bien d'autres choses.

Cela ne s'appliquera qu'à la sérialisation JSON de l'API Web. Les autres sérialisations de l'application (sérialisation XML de l'API Web, MVC JsonResult ...) ne seront pas affectées par ce paramètre.

JotaBe
la source
4
J'aime cette solution beaucoup mieux que d'ajouter des attributs [DataContract] et [DataMember] partout. Merci!!
Mark Good
1
Ce n'est pas quelque chose que vous devriez utiliser tout le temps, mais c'est une astuce intéressante. Une sorte de pied de biche qui vous aide à contourner les situations désordonnées où vous n'avez pas le luxe de changer les modèles ou de refactoriser la base de code en profondeur.
uygar.raf
Vous avez raison de dire que ce n'est pas la meilleure façon de procéder. Cependant, à certaines occasions, la refactorisation n'est pas seulement un luxe, mais ce n'est pas du tout faisable. Par exemple, si la base de code utilise WCF ou la sérialisation XML, elle nécessite un contrat de données ou des attributs de sérialisation XML. Vous ne pouvez pas changer cela. Heureusement, JSON.NET est très puissant: il prend en charge le contrat de données, la sérialisation XML et ses propres attributs, et vous pouvez contrôler comment il les utilise pour la sérialisation, voire les ignorer complètement. Et vous pouvez même ajouter votre propre implémentation. Bien sûr, je préfère rester propre et sans attributs.
JotaBe
C'est ainsi que cela devrait fonctionner par défaut! Pourquoi avons-nous toujours wabt backingfield absurde dans notre flux sérialisé?
Byron Whitlock
1
Si vous utilisez une API Web et ciblez la version 4 du framework .net, vous devrez mettre à jour le package Netwonsoft.Json pour que cela fonctionne, c'est-à-dire Update-Package Newtonsoft.Json.
pblack
0

Les attributs [DataContract] ne fonctionnaient pas pour moi, donc ce n'était pas une option.

XmlSerializer ignore [XmlAttribute] dans WebApi

La résolution ci-dessus l'a résolu pour moi.

GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;
JanBorup
la source