.NET WebAPI 직렬화 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도 포함됩니다.


답변:


126

기본적 으로 웹 API 를 사용 [Serializable]하거나 [DataContract]작업 할 필요가 없습니다 .

모델을 그대로두면 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]을 제거해야했습니다. 감사.
Micah

감사합니다 Filip, 캐시 때문에 속성을 유지해야합니다 .. BTW, 나는 당신의 블로그의 열렬한 팬입니다 .. 계속 오세요!
Stephen Patten 2013 년

20
이것은 끔찍합니다. Microsoft가 없습니다 이제까지 는 직렬화에 올 때 올바른 아무것도 할?
Chris Marisic 2013 년

아래 내 답변에서 볼 수 있듯이 더 일반적인 해결책이 있습니다.
JotaBe

아마도 직렬화의 문제는 "올바른"의 정의 일 것입니다. 모든 사람은 자신의 방식으로 데이터를 필요로합니다.
Luiz Felipe

94

더 일반적인 솔루션이 있습니다. [Serializable]속성 을 무시하도록 Json Serializer를 구성 하여 클래스의 속성을 변경할 필요가 없습니다.

응용 프로그램 시작, 즉 Global.asax Application_Start이벤트 에서이 구성을 변경해야합니다 .

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

날짜 직렬화에 대한 형식 지정 및 기타 여러 가지와 같이 Json 직렬화에 대한 기타 변경을 수행 할 수도 있습니다.

이는 Web API JSON 직렬화에만 적용됩니다. 앱의 다른 직렬화 (Web API XML 직렬화, MVC JsonResult ...)는이 설정의 영향을받지 않습니다.


4
이 솔루션이 [DataContract] 및 [DataMember] 속성을 모든 곳에 추가하는 것보다 훨씬 좋습니다. 감사합니다!!
Mark Good

1
항상 사용해야하는 것은 아니지만 이것은 깔끔한 트릭입니다. 모델을 변경하거나 코드베이스를 심층적으로 리팩토링 할 수없는 복잡한 상황을 피할 수 있도록 도와주는 일종의 지렛대입니다.
uygar.raf

이것이 최선의 방법이 아니라는 것이 맞습니다. 그러나 어떤 경우에는 리팩토링이 사치 일뿐만 아니라 전혀 실현 가능하지도 않습니다. 예를 들어 코드베이스에서 WCF 또는 XML 직렬화를 사용하는 경우 데이터 계약 또는 XML 직렬화 특성이 필요합니다. 당신은 그것을 바꿀 수 없습니다. 다행히 JSON.NET은 매우 강력합니다. 데이터 계약, XML 직렬화 및 자체 특성을 지원하며 직렬화에 사용하는 방법을 제어하거나 완전히 무시할 수도 있습니다. 또한 자체 구현을 추가 할 수도 있습니다. 물론 속성없이 깔끔한 걸쇠를 유지하는 것을 선호합니다.
JotaBe 2015

이것이 기본적으로 작동하는 방식입니다! 왜 우리는 직렬화 된 스트림에서 backingfield 넌센스를 wabt합니까?
Byron Whitlock 2015

1
웹 API를 사용 중이고 .net 프레임 워크 버전 4를 대상으로하는 경우이 작업을 수행하려면 Netwonsoft.Json 패키지를 업데이트해야합니다 Update-Package Newtonsoft.Json.
pblack


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.