.NET WebAPI Serialization k_BackingField Nastiness

86

Kiedy serializuję następujące elementy:

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

Dostaję ten obrzydliwy bałagan:

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

Co daje? Jak mogę to zrobić ładnie? Odpowiedzi JSON zawierają również k_BackingField

Micheasza
źródło
To mi pomogło: stackoverflow.com/questions/15388452/ ...
granadaCoder

Odpowiedzi:

126

Domyślnie nie musisz używać [Serializable]ani [DataContract]pracować z Web API.

Po prostu pozostaw model bez zmian, a interfejs API sieci Web będzie serializował wszystkie właściwości publiczne.

Tylko jeśli chcesz mieć większą kontrolę nad zawartością, możesz ozdobić swoją klasę [DataContract]i właściwości, które mają być uwzględnione [DataMember](ponieważ zarówno DCS, jak i JSON.NET respektują te atrybuty).

Jeśli z jakiegoś powodu potrzebujesz [Serializable]swojej klasy (tj. Z jakiegoś powodu serializujesz ją do strumienia pamięci, robisz głębokie kopie itp.), Musisz użyć obu atrybutów w połączeniu, aby zapobiec nazwom pól zapasowych:

[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.
źródło
6
To było to - po prostu musiałem usunąć [Serializable]. Dzięki.
Micah
Dzięki Filip, muszę zachować atrybuty ze względu na pamięć podręczną ... Przy okazji, jestem zagorzałym fanem Twojego bloga ... tak dalej!
Stephen Patten
20
To jest po prostu straszne. Dlaczego firma Microsoft NIGDY nie może zrobić nic poprawnego, jeśli chodzi o serializację?
Chris Marisic
Istnieje bardziej ogólne rozwiązanie, które pokazuję w mojej odpowiedzi poniżej.
JotaBe
Być może problemem z serializacją jest określenie „poprawnej”, każdy potrzebuje danych na swój sposób.
Luiz Felipe
94

Istnieje bardziej ogólne rozwiązanie: możesz skonfigurować Json Serializer tak, aby ignorował [Serializable]atrybut, dzięki czemu nie musisz zmieniać atrybutów w swoich klasach.

Tę zmianę konfiguracji należy wprowadzić przy starcie aplikacji, czyli w Application_Startzdarzeniu Global.asax :

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

Możesz również wprowadzić inne zmiany w serializacji Json, takie jak określanie formatów serializacji dat i wiele innych rzeczy.

Dotyczy to tylko serializacji JSON interfejsu API sieci Web. Inne serializacje w aplikacji (serializacja XML interfejsu API sieci Web, MVC JsonResult ...) nie będą miały wpływu na to ustawienie.

JotaBe
źródło
4
To rozwiązanie podoba mi się o wiele lepiej niż dodawanie wszędzie atrybutów [DataContract] i [DataMember]. Dziękuję Ci!!
Mark Good
1
Nie jest to coś, czego powinieneś używać przez cały czas, ale to fajna sztuczka. Coś w rodzaju łomu, który pomaga obejść nieporządne sytuacje, w których nie masz luksusu zmiany modeli lub głębokiej refaktoryzacji bazy kodu.
uygar.raf
Masz rację, że to nie jest najlepszy sposób na zrobienie tego. Jednak w niektórych przypadkach refaktoryzacja jest nie tylko luksusem, ale w ogóle nie jest wykonalna. Na przykład jeśli baza kodu używa WCF lub serializacji XML, wymaga atrybutów kontraktu danych lub serializacji XML. Nie możesz tego zmienić. Na szczęście JSON.NET jest bardzo potężny: obsługuje Kontrakty danych, serializację XML i własne atrybuty, i możesz kontrolować, jak używa ich do serializacji, a nawet całkowicie je ignorować. Możesz nawet dodać własną implementację. Oczywiście wolę zachować czystość bez atrybutów.
JotaBe
Tak to powinno działać domyślnie! Dlaczego w naszym serializowanym strumieniu szukamy bzdur z pola drugoplanowego?
Byron Whitlock,
1
Jeśli korzystasz z interfejsu API sieci Web i celujesz w wersję 4 platformy .net, musisz zaktualizować pakiet Netwonsoft.Json, aby to działało, tj Update-Package Newtonsoft.Json.
pblack
0

Atrybuty [DataContract] nie działały dla mnie, więc nie było takiej opcji.

XmlSerializer ignoruje [XmlAttribute] w WebApi

Powyższa rezolucja rozwiązała to za mnie.

GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;
JanBorup
źródło