web-dev-qa-db-fra.com

Sérialisation des API Web .NET k__BackingField Nastiness

Quand je sérialiser ce qui suit:

[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 bordel dégoutant:

<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 cela joli? Les réponses JSON contiennent également le k_BackingField

79
Micah

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

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

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 dans [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 le sérialisez dans un flux de mémoire pour une raison quelconque, en effectuant des copies complètes, etc.), vous devez utiliser les deux attributs conjointement pour éviter les noms de champs 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; }
}
120
Filip W

Il existe une solution plus générale: vous pouvez configurer le sérialiseur Json pour qu'il ignore l'attribut [Serializable], de sorte que vous n'ayez pas à modifier les attributs dans vos classes.

Vous devez apporter cette modification de configuration au démarrage de l’application, c’est-à-dire dans l’événement Global.asax Application_Start:

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, telles que la spécification des formats de sérialisation des dates, etc.

Cela s'appliquera uniquement à 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.

84
JotaBe

Essayez d’utiliser DataContract au lieu de Serializable pour marquer votre classe. Pour plus de détails sur pourquoi, consultez ce bon article de blog sur la sérialisation des propriétés automatiques.

2
Sixto Saez

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;
0
JanBorup