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]né [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.