Serialização do .NET WebAPI k_BackingField Nastiness


86

Quando eu serializo o seguinte:

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

Eu fico com essa bagunça nojenta:

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

O que da? Como posso deixar isso bonito? As respostas JSON também contêm o k_BackingField


Respostas:


126

Por padrão, você não precisa usar [Serializable]nem [DataContract]trabalhar com Web API.

Basta deixar seu modelo como está, e a API da Web serializará todas as propriedades públicas para você.

Apenas se quiser ter mais controle sobre o que está incluído, você então decora sua classe com [DataContract]e as propriedades a serem incluídas [DataMember](porque DCS e JSON.NET refletem esses atributos).

Se, por algum motivo, você precisar do [Serializable]em sua classe (ou seja, você está serializando-o em um fluxo de memória por algum motivo, fazendo cópias profundas etc.), você deve usar os dois atributos em conjunto para evitar os nomes dos campos de apoio:

[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
Era isso - eu só precisava remover o [Serializável]. Obrigado.
Micah

Obrigado Filip, tenho que manter os atributos por causa do cache .. BTW, sou um ávido fã do seu blog .. continue assim!
Stephen Patten

20
Isso é simplesmente terrível. Por que a Microsoft NUNCA pode fazer nada correto quando se trata de serialização?
Chris Marisic de

Existe uma solução mais geral, como mostro na minha própria resposta abaixo.
JotaBe

Talvez o problema com a serialização seja a definição de "correto", todos precisam de dados em seu caminho.
Luiz Felipe

94

Existe uma solução mais geral: você pode configurar o Json Serializer para ignorar o [Serializable]atributo, de forma que você não precise alterar os atributos em suas classes.

Você deve fazer essa alteração de configuração no início do aplicativo, ou seja, no Application_Startevento Global.asax :

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

Você também pode fazer outras alterações na serialização Json, como especificar formatos para serializar datas e muitas outras coisas.

Isso se aplica apenas à serialização JSON da API da Web. As outras serializações no aplicativo (serialização XML da API da Web, MVC JsonResult ...) não serão afetadas por esta configuração.


4
Gosto muito mais dessa solução do que adicionar atributos [DataContract] e [DataMember] em todos os lugares. Obrigado!!
Mark Good

1
Não é algo que você deveria usar o tempo todo, mas é um truque interessante. Uma espécie de alavanca que o ajuda a contornar situações complicadas nas quais você não tem o luxo de alterar os modelos ou refatorar a base de código em profundidade.
uygar.raf

Você está certo de que esta não é a melhor maneira de fazer isso. No entanto, em algumas ocasiões, refatorar não é apenas um luxo, mas também não é viável. Por exemplo, se a base de código usa WCF ou XML Serialization, ela exige um contrato de dados ou atributos de serialização XML. Você não pode mudar isso. Felizmente, o JSON.NET é muito poderoso: ele suporta contrato de dados, serialização XML e seus próprios atributos, e você pode controlar como ele os usa para serialização ou até mesmo ignorá-los totalmente. E você pode até adicionar sua própria implementação. Claro, prefiro manter uma classe limpa, sem atributos.
JotaBe

É assim que deve funcionar por padrão! Por que sempre usamos um absurdo de backingfield em nosso stream serializado?
Byron Whitlock,

1
Se você estiver usando api web e são dirigidas a versão 4 do .NET Framework, então você vai precisar atualizar o pacote Netwonsoft.Json para que isso funcione, ou seja Update-Package Newtonsoft.Json.
pblack 01 de


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.