2016-07-17 7 views
1

空の.net残りのapiは、XMLしか受け付けません。 コントローラメソッドが直接シリアル化したいクラスを返す場合、問題はありません。しかし、すべてのコントローラメソッドがHttpResponseMessageを返すように、レスポンスラッパーを使用したいと思います。HttpResponseMessageはコンテンツをシリアル化できません

だから、この作品: 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引数は例えば、正しくobjectとして宣言されていない入力する必要がある。:

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

XmlMediaTypeFormattertypeof(T)ではなくvalue.GetType()を使用して、そのXmlSerializerを構築するため、このソリューションは動作します。 source codeから:

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

私たちは(ObjectContent<T>からtypeof(T)としてWriteToStreamAsync()に渡される)typeは、シリアライザの構築に使用されていることがわかります。 object valueはありません。代わりにvalue.GetType()を使用することにしましたが、そうしなかった可能性があります。 (typeof(Foo))は、シリアライザ(typeof(object))の構築に使用された型と同じではなく、既知の型のobjectの1つと同じではないため、シリアライザは例外をスローします。

+0

ありがとう!なぜそれがこの方法(xmlのnoobie)で動作するのか完全に理解しているとは言えませんが、それがありました!しかし、私は@Alleksey L.が指摘した方向に移動しなければならないと思う。一方、これを使用します。 – John

+0

@John - 解説付きの解答を更新しました。 – dbc

関連する問題