Serializzazione .NET WebAPI k_BackingField Nastiness


86

Quando serializzo quanto segue:

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

Ottengo questo disordine disgustoso:

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

Cosa succede? Come posso renderlo carino? Le risposte JSON contengono anche k_BackingField


Risposte:


126

Per impostazione predefinita, non è necessario utilizzare né [Serializable][DataContract]lavorare con l'API Web.

Lascia il tuo modello così com'è e l'API Web serializzerà tutte le proprietà pubbliche per te.

Solo se vuoi avere un maggiore controllo su ciò che è incluso, allora decori la tua classe con [DataContract]e le proprietà da includere [DataMember](perché sia ​​DCS che JSON.NET rispettano questi attributi).

Se per qualche motivo, hai bisogno del [Serializable]sulla tua classe (cioè lo stai serializzando in un flusso di memoria per qualche motivo, eseguendo copie profonde ecc.), Allora devi usare entrambi gli attributi insieme per prevenire i nomi dei campi di supporto:

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

6
Ecco fatto ... Avevo solo bisogno di rimuovere [Serializable]. Grazie.
Michea

Grazie Filip, devo mantenere gli attributi a causa della cache .. A proposito, sono un fan accanito del tuo blog .. continualo!
Stephen Patten

20
Questo è semplicemente terribile. Perché Microsoft non può MAI fare nulla di corretto quando si tratta di serializzazione?
Chris Marisic

C'è una soluzione più generale, come mostro nella mia risposta di seguito.
JotaBe

Forse il problema con la serializzazione è la definizione di "corretto", tutti hanno bisogno dei dati a modo loro.
Luiz Felipe

94

C'è una soluzione più generale: puoi configurare Json Serializer per ignorare l' [Serializable]attributo, in modo da non dover modificare gli attributi nelle tue classi.

È necessario apportare questa modifica alla configurazione all'avvio dell'applicazione, ovvero Application_Startnell'evento Global.asax :

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

Puoi anche apportare altre modifiche alla serializzazione Json, come specificare i formati per la serializzazione delle date e molte altre cose.

Ciò si applicherà solo alla serializzazione JSON dell'API Web. Le altre serializzazioni nell'app (serializzazione XML dell'API Web, MVC JsonResult ...) non saranno interessate da questa impostazione.


4
Questa soluzione mi piace molto di più rispetto all'aggiunta degli attributi [DataContract] e [DataMember] ovunque. Grazie!!
Mark Good

1
Non è qualcosa che dovresti usare sempre, ma questo è un bel trucco. Una specie di piede di porco che ti aiuta ad aggirare le situazioni disordinate in cui non hai il lusso di cambiare i modelli o refactoring della base di codice in profondità.
uygar.raf

Hai ragione che questo non è il modo migliore per farlo. Tuttavia, in alcune occasioni il refactoring non è solo un lusso, ma non è affatto fattibile. Ad esempio, se la codebase utilizza WCF o la serializzazione XML, richiede il contratto dati o gli attributi di serializzazione XML. Non puoi cambiarlo. Fortunatamente JSON.NET è molto potente: supporta il contratto dati, la serializzazione XML ei suoi attributi e puoi controllare come li usa per la serializzazione o persino ignorarli completamente. E puoi persino aggiungere la tua implementazione. Naturalmente, preferisco mantenere una classificazione pulita senza attributi.
JotaBe

Ecco come dovrebbe funzionare di default! Perché abbiamo mai detto sciocchezze di backingfield nel nostro flusso serializzato?
Byron Whitlock

1
Se stai usando web api e stai prendendo di mira la versione 4 del framework .net, dovrai aggiornare il pacchetto Netwonsoft.Json affinché funzioni, ad es Update-Package Newtonsoft.Json.
pblack


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.