.NET WebAPI Serialization k_BackingField Nastiness


86

เมื่อฉันทำให้เป็นอนุกรมต่อไปนี้:

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

ฉันมีระเบียบที่น่าขยะแขยงนี้:

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

สิ่งที่ช่วยให้? ฉันจะทำให้มันสวยได้อย่างไร? การตอบสนอง JSON ยังมี k_BackingField


สิ่งนี้ช่วยฉันได้: stackoverflow.com/questions/15388452/…
granadaCoder

คำตอบ:


126

โดยเริ่มต้นที่คุณไม่จำเป็นต้องใช้ค่า[Serializable]มิได้[DataContract]ที่จะทำงานร่วมกับเว็บ API

เพียงแค่ปล่อยโมเดลของคุณไว้ตามที่เป็นอยู่และ Web API จะทำให้คุณสมบัติสาธารณะทั้งหมดเป็นอนุกรมสำหรับคุณ

เฉพาะในกรณีที่คุณต้องการควบคุมสิ่งที่รวมอยู่ให้มากขึ้นจากนั้นคุณจะตกแต่งคลาสของคุณด้วย[DataContract]และคุณสมบัติที่จะรวมด้วย[DataMember](เนื่องจากทั้ง DCS และ JSON.NET ตอบสนองคุณสมบัติเหล่านี้)

หากด้วยเหตุผลบางประการคุณต้องใช้[Serializable]ในชั้นเรียนของคุณ (เช่นคุณกำลังต่ออนุกรมลงในสตรีมหน่วยความจำด้วยเหตุผลบางประการการทำสำเนาแบบลึก ฯลฯ ) คุณต้องใช้แอตทริบิวต์ทั้งสองร่วมกันเพื่อป้องกันไม่ให้ชื่อเขตข้อมูลสำรอง

[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
แค่นั้นเอง - ฉันแค่ต้องการลบ [Serializable] ขอบคุณ.
คาห์

ขอบคุณ Filip ต้องเก็บคุณลักษณะไว้เพราะแคช .. BTW ฉันเป็นแฟนตัวยงของบล็อกของคุณ .. ให้มา!
Stephen Patten

20
แค่นี้ก็แย่แล้ว เหตุใด Microsoft EVERจึงไม่สามารถแก้ไขอะไรได้ในเรื่องการทำให้เป็นอนุกรม
Chris Marisic

มีวิธีแก้ปัญหาทั่วไปมากขึ้นดังที่ฉันแสดงในคำตอบของตัวเองด้านล่าง
JotaBe

บางทีปัญหาเกี่ยวกับการทำให้เป็นอนุกรมเป็นคำจำกัดความของ "ถูกต้อง" ทุกคนต้องการข้อมูลในแบบของตน
Luiz Felipe

94

มีวิธีแก้ปัญหาทั่วไปมากขึ้น: คุณสามารถกำหนดค่า Json Serializer ให้ละเว้น[Serializable]แอตทริบิวต์เพื่อที่คุณจะได้ไม่ต้องเปลี่ยนแอตทริบิวต์ในคลาสของคุณ

คุณควรทำการเปลี่ยนแปลงการกำหนดค่านี้ในการเริ่มต้นแอปพลิเคชันเช่นในApplication_Startเหตุการณ์Global.asax :

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

คุณยังสามารถทำการเปลี่ยนแปลงอื่น ๆ ในการทำให้อนุกรม Json เช่นการระบุรูปแบบสำหรับการทำให้เป็นอนุกรมวันที่และอื่น ๆ อีกมากมาย

สิ่งนี้จะใช้กับการทำให้เป็นอนุกรม Web API JSON เท่านั้น การทำให้เป็นอนุกรมอื่น ๆ ในแอป (การทำให้เป็นอนุกรม XML ของ Web API, MVC JsonResult ... ) จะไม่ได้รับผลกระทบจากการตั้งค่านี้


4
ฉันชอบโซลูชันนี้ดีกว่าการเพิ่มแอตทริบิวต์ [DataContract] และ [DataMember] ทุกที่ ขอขอบคุณ!!
Mark Good

1
ไม่ใช่สิ่งที่คุณควรใช้ตลอดเวลา แต่นี่เป็นเคล็ดลับที่เรียบร้อย ชะแลงชนิดหนึ่งที่ช่วยให้คุณหลีกเลี่ยงสถานการณ์ที่ยุ่งเหยิงโดยที่คุณไม่มีความหรูหราในการเปลี่ยนโมเดลหรือปรับโครงสร้างโค้ดเบสในเชิงลึก
uygar.raf

คุณคิดถูกที่นี่ไม่ใช่วิธีที่ดีที่สุด อย่างไรก็ตามในบางครั้งการปรับโครงสร้างใหม่ไม่ใช่แค่ความหรูหราเท่านั้น แต่ยังไม่เป็นไปได้เลย ตัวอย่างเช่นถ้า codebase ใช้ WCF หรือ XML Serialization จะต้องมีแอตทริบิวต์ Data Contract หรือ XML serialization คุณไม่สามารถเปลี่ยนแปลงได้ โชคดีที่ JSON.NET มีประสิทธิภาพมาก: รองรับ Data Contract, XML serialization และแอตทริบิวต์ของตัวเองและคุณสามารถควบคุมวิธีที่จะใช้สำหรับการทำให้เป็นอนุกรมหรือแม้แต่ละเว้นอย่างเต็มที่ และคุณยังสามารถเพิ่มการใช้งานของคุณเองได้อีกด้วย แน่นอนฉันชอบที่จะรักษาระดับความสะอาดโดยไม่มีคุณลักษณะ
JotaBe

นี่คือวิธีการทำงานโดยปริยาย! เหตุใดเราจึงหันเหความไร้สาระสำรองในสตรีมอนุกรมของเรา
Byron Whitlock

1
หากคุณกำลังใช้ API เว็บและการกำหนดเป้าหมายรุ่นที่ 4 ของกรอบ net แล้วคุณจะต้องอัปเดตแพคเกจ Netwonsoft.Json Update-Package Newtonsoft.Jsonในการสั่งซื้อสำหรับการทำงานคือ
pblack

2

ลองใช้ DataContract แทน Serializable เพื่อทำเครื่องหมายชั้นเรียนของคุณ สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับสาเหตุโปรดดูที่บล็อกโพสต์ที่ดีเกี่ยวกับการทำให้เป็นอนุกรมคุณสมบัติอัตโนมัติ


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.