2016-07-17 8 views
1

비어 있습니다 .net 나머지 api는 XML만을 허용합니다. 컨트롤러 메서드가 직접 직렬화하려는 클래스를 반환하면 문제가 없습니다. 하지만 모든 컨트롤러 메서드가 HttpResponseMessage을 반환하도록 응답 래퍼를 사용하고 싶습니다.HttpResponseMessage가 내용을 serialize 할 수 없습니다.

그래서이 작동합니다 FooController.cs :

public FooResponse PostFoo(FooRequest foo) 
{ 
    var fooVal = fooBll.GetFoo(); 
    return new FooResponse { Foo = fooVal;}; 
} 

그러나이되지 않습니다 FooController.cs :

public HttpResponseMessage PostFoo(FooRequest foo) 
{ 
    var fooVal = fooBll.GetFoo(); 
    HttpResponseMesage response; 
    response = fooBll.GetSuccessResponse(Url, new FooResponse {Foo = foovVal;}); 
    return response ; 
} 

ResponseBLL.cs가 :

public HttpResponseMessage GetSuccessResponse(UrlHelper Url, object obj) 
{ 
    this.requestMsg = HttpContext.Current.Items["MS_HttpRequestMessage"] as HttpRequestMessage; 
    this.responseMsg = this.requestMsg.CreateResponse(HttpStatusCode.OK, obj); 
    this.responseMsg.Headers.Location = HttpContext.Current.Request.Url; 
    return this.responseMsg; 
} 

FooBLL 상속 ResponseBLL, 그래서 전화 할 수 있습니다 fooBll.GetSuccessResponse . WebApiConfig.cs에서

나는이 : 내가 얻을

config.Formatters.XmlFormatter.UseXmlSerializer = true; 
config.Formatters.Remove(config.Formatters.JsonFormatter); 

오류 유형의 FooResponse이 예상되지

입니다. 정적으로 알려지지 않은 형식을 지정하려면 XmlInclude 또는 SoapInclude 특성을 사용하십시오.

이제는이 문제에 대해 많은 질문을하고 있으며 저를 신뢰합니다. 나는 성공하지 못했지만 모두 통과했습니다. 내가 생각할 수있는 모든 가능한 조합에서 [DataContract], [DataMember], [Serializable][XmlInclude] 속성을 시도했다. FooBLL 클래스에 [XmlInclude(typeof(FooResponse))], ResponseBLL에 [XmlInclude(typeof(FooBLL))] 등이 있습니다.

도와 주시면 감사하겠습니다.

+1

액션 필터 –

+0

@AlekseyL을 사용하여 농축 왕을하는 것이 훨씬 더 깨끗합니다. 고마워, 나는 그것에 대해 조사 할 것이다. 기본적으로이 래퍼가 다른 방식의 컨텐트를 반환 할 수있는 방법 이었기 때문에이 래퍼를 원했던 이유는 무엇입니까? 'GetFailResponse' 메쏘드도 있습니다.이 메쏘드는 내용 대신에 오류에 대한 정보를 반환합니다. 그것 없이는 내가 볼 수있는 한 그것을 할 수 없다. 나는'FooResponse'와 다른 것을 돌려줘야한다. – John

+1

예외 필터 또는 예외 처리기로 처리 할 수 ​​있습니다 –

답변

1

HttpRequestMessageExtensions.CreateResponse<T>()은 일반적인 방법입니다. T Value 인수는 XmlMediaTypeFormattertypeof(T)보다는 value.GetType()를 사용하여 XmlSerializer을 구성하기 때문에

public HttpResponseMessage GetSuccessResponse<T>(UrlHelper Url, T obj) 
{ 
    this.requestMsg = HttpContext.Current.Items["MS_HttpRequestMessage"] as HttpRequestMessage; 
    this.responseMsg = this.requestMsg.CreateResponse(HttpStatusCode.OK, obj); 
    this.responseMsg.Headers.Location = HttpContext.Current.Request.Url; 
    return this.responseMsg; 
} 

이 솔루션은 작동 : 제대로 object으로 선언되지 입력해야 예컨대 있습니다. source code에서 :

protected internal virtual object GetSerializer(Type type, object value, HttpContent content) 
    { 
     return GetSerializerForType(type); 
    } 

우리는 (ObjectContent<T>에서 typeof(T)으로 WriteToStreamAsync()에 전달 됨) type이 시리얼 건설에 사용되는 것을 볼 수 있습니다. object value은 그렇지 않습니다. Microsoft는 대신 value.GetType()을 사용할 수는 있지만 실제로 사용하지는 못했습니다. 그런 다음 serializer (이 경우 typeof(Foo))의 실제 유형이 serializer (typeof(object))를 구성하는 데 사용 된 유형과 같지 않거나 object의 알려진 유형 중 하나이기 때문에 serializer가 예외를 throw합니다.

+0

고마워요! 내가 왜 이런 방식으로 작동하는지 완벽하게 이해한다고 말할 수는 없다. (noobie in xml),하지만 그렇게했다. 그러나 나는 @Alleksey L.이 지적한 방향으로 움직여야 할 것이라고 생각한다. 한편으로 이것을 사용할 것입니다. – John

+0

@ 존 - 설명이있는 대답이 업데이트되었습니다. – dbc