.NET WebAPI-Serialisierung k_BackingField Nastiness

86

Wenn ich folgendes serialisiere:

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

Ich bekomme dieses ekelhafte Durcheinander:

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

Was gibt? Wie kann ich das hübsch machen? JSON-Antworten enthalten auch das k_BackingField

Micah
quelle
Dies hat mir geholfen: stackoverflow.com/questions/15388452/…
granadaCoder

Antworten:

126

Standardmäßig müssen Sie weder die Web-API verwenden [Serializable]noch [DataContract]mit ihr arbeiten.

Lassen Sie Ihr Modell einfach so, wie es ist, und die Web-API würde alle öffentlichen Eigenschaften für Sie serialisieren.

Nur wenn Sie mehr Kontrolle darüber haben möchten, was enthalten ist, dekorieren Sie Ihre Klasse mit [DataContract]und den Eigenschaften, die enthalten sein sollen [DataMember](da sowohl DCS als auch JSON.NET diese Attribute respektieren).

Wenn Sie aus irgendeinem Grund das [Serializable]für Ihre Klasse benötigen (dh Sie serialisieren es aus irgendeinem Grund in einen Speicherstrom, erstellen tiefe Kopien usw.), müssen Sie beide Attribute zusammen verwenden, um die Namen der Hintergrundfelder zu verhindern:

[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.
quelle
6
Das war es - ich musste nur die [Serializable] entfernen. Vielen Dank.
Micah
Danke Filip, muss die Attribute wegen des Cache behalten. Übrigens, ich bin ein begeisterter Fan deines Blogs. Mach weiter so!
Stephen Patten
20
Das ist einfach schrecklich. Warum kann Microsoft bei der Serialisierung NIEMALS etwas richtig machen?
Chris Marisic
Es gibt eine allgemeinere Lösung, wie ich in meiner eigenen Antwort unten zeige.
JotaBe
Vielleicht liegt das Problem bei der Serialisierung in der Definition von "richtig", jeder braucht Daten auf seine Weise.
Luiz Felipe
93

Es gibt eine allgemeinere Lösung: Sie können den Json Serializer [Serializable]so konfigurieren, dass das Attribut ignoriert wird, sodass Sie die Attribute in Ihren Klassen nicht ändern müssen.

Sie sollten diese Konfigurationsänderung beim Start der Anwendung vornehmen, dh im Application_StartEreignis Global.asax :

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

Sie können auch andere Änderungen an der Json-Serialisierung vornehmen, z. B. die Angabe von Formaten für die Serialisierung von Datumsangaben und viele andere Dinge.

Dies gilt nur für die JSON-Serialisierung der Web-API. Die anderen Serialisierungen in der App (Web-API-XML-Serialisierung, MVC JsonResult ...) sind von dieser Einstellung nicht betroffen.

JotaBe
quelle
4
Diese Lösung gefällt mir viel besser, als überall die Attribute [DataContract] und [DataMember] hinzuzufügen. Danke dir!!
Mark Good
1
Nicht etwas, das Sie ständig verwenden sollten, aber dies ist ein ordentlicher Trick. Eine Art Brechstange, die Ihnen hilft, unordentliche Situationen zu umgehen, in denen Sie nicht den Luxus haben, die Modelle zu ändern oder die Codebasis gründlich umzugestalten.
uygar.raf
Sie haben Recht, dass dies nicht der beste Weg ist, dies zu tun. In einigen Fällen ist die Umgestaltung jedoch nicht nur ein Luxus, sondern überhaupt nicht machbar. Wenn die Codebasis beispielsweise WCF oder XML-Serialisierung verwendet, sind Datenvertrags- oder XML-Serialisierungsattribute erforderlich. Das kannst du nicht ändern. Glücklicherweise ist JSON.NET sehr leistungsfähig: Es unterstützt Datenverträge, XML-Serialisierung und eigene Attribute, und Sie können steuern, wie sie für die Serialisierung verwendet werden, oder sie sogar vollständig ignorieren. Sie können sogar Ihre eigene Implementierung hinzufügen. Natürlich ziehe ich es vor, ohne Attribute sauber zu bleiben.
JotaBe
So sollte es standardmäßig funktionieren! Warum wabt wir in unserem serialisierten Stream immer Backingfield-Unsinn?
Byron Whitlock
1
Wenn Sie eine Web-API verwenden und auf Version 4 des .net-Frameworks abzielen, müssen Sie das Netwonsoft.Json-Paket aktualisieren, damit dies funktioniert Update-Package Newtonsoft.Json.
Schwarz
0

Die [DataContract] -Attribute haben bei mir nicht funktioniert, daher war dies keine Option.

XmlSerializer ignoriert [XmlAttribute] in WebApi

Die obige Lösung hat es für mich gelöst.

GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;
JanBorup
quelle