.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


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

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.


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


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.