.NET WebAPI Serialization k_BackingField Nastiness

86

Ketika saya membuat serial berikut ini:

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

Saya mendapatkan kekacauan yang menjijikkan ini:

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

Apa yang memberi? Bagaimana saya bisa membuatnya cantik? Respons JSON juga berisi k_BackingField

Mikha
sumber
Ini membantu saya: stackoverflow.com/questions/15388452/…
granadaCoder

Jawaban:

126

Secara default, Anda tidak perlu menggunakan [Serializable]atau [DataContract]bekerja dengan API Web.

Biarkan model Anda sebagaimana adanya, dan Web API akan membuat serialisasi semua properti publik untuk Anda.

Hanya jika Anda ingin memiliki lebih banyak kendali tentang apa yang disertakan, Anda kemudian menghias kelas Anda dengan [DataContract]dan properti yang akan disertakan [DataMember](karena DCS dan JSON.NET menghormati atribut ini).

Jika karena alasan tertentu, Anda memerlukan [Serializable]pada kelas Anda (yaitu Anda membuat serialisasi ke dalam aliran memori untuk beberapa alasan, melakukan salinan dalam, dll), maka Anda harus menggunakan kedua atribut dalam hubungannya untuk mencegah nama bidang dukungan:

[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
sumber
6
Itu saja-- Saya hanya perlu menghapus [Serializable]. Terima kasih.
Mikha
Terima kasih Filip, saya harus menyimpan atributnya karena cache .. BTW, saya penggemar berat blog Anda .. teruslah datang!
Stephen Patten
20
Ini sangat buruk. Mengapa Microsoft TIDAK PERNAH melakukan sesuatu yang benar dalam hal serialisasi?
Chris Marisic
Ada solusi yang lebih umum, seperti yang saya tunjukkan dalam jawaban saya sendiri di bawah ini.
JotaBe
Mungkin masalah dengan serialisasi adalah definisi "benar", setiap orang membutuhkan data di jalan mereka.
Luiz Felipe
94

Ada solusi yang lebih umum: Anda dapat mengkonfigurasi Json Serializer untuk mengabaikan [Serializable]atribut, sehingga Anda tidak perlu mengubah atribut di kelas Anda.

Anda harus membuat perubahan konfigurasi ini di awal aplikasi, yaitu di Application_Startacara Global.asax :

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

Anda juga dapat membuat perubahan lain pada serialisasi Json, seperti menentukan format untuk serialisasi tanggal, dan banyak hal lainnya.

Ini hanya akan berlaku untuk serialisasi JSON API Web. Serialisasi lain dalam aplikasi (serialisasi XML API Web, MVC JsonResult ...) tidak akan terpengaruh oleh setelan ini.

JotaBe
sumber
4
Saya menyukai solusi ini jauh lebih baik daripada menambahkan atribut [DataContract] dan [DataMember] di mana-mana. Terima kasih!!
Mark Good
1
Bukan sesuatu yang harus Anda gunakan setiap saat, tetapi ini adalah trik yang bagus. Semacam linggis yang membantu Anda mengatasi situasi berantakan di mana Anda tidak memiliki kemewahan untuk mengubah model atau memfaktorkan ulang basis kode secara mendalam.
uygar.raf
Anda benar bahwa ini bukan cara terbaik untuk melakukannya. Namun, dalam beberapa kesempatan, refactoring tidak hanya mewah, tetapi tidak layak sama sekali. Misalnya, jika basis kode menggunakan WCF, atau Serialisasi XML, itu memerlukan atribut Kontrak Data atau serialisasi XML. Anda tidak bisa mengubahnya. Untungnya JSON.NET sangat kuat: ia mendukung Kontrak Data, serialisasi XML dan atributnya sendiri, dan Anda dapat mengontrol bagaimana ia menggunakannya untuk serialisasi, atau bahkan mengabaikannya sepenuhnya. Dan Anda bahkan dapat menambahkan implementasi Anda sendiri. Tentu saja, saya lebih suka menjaga kebersihan tanpa atribut.
JotaBe
Beginilah cara kerjanya secara default! Mengapa kita melakukan omong kosong backingfield dalam streaming serial kita?
Byron Whitlock
1
Jika Anda menggunakan api web dan menargetkan versi 4 dari kerangka kerja .net maka Anda perlu memperbarui paket Netwonsoft.Json agar ini berfungsi, yaitu Update-Package Newtonsoft.Json.
pblack
0

Atribut [DataContract] tidak berfungsi untuk saya, jadi itu bukan opsi.

XmlSerializer mengabaikan [XmlAttribute] di WebApi

Resolusi di atas menyelesaikannya untuk saya.

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