2016-10-05 5 views
4

WebApiの差別化された結合の結果からクリーンjsonを返すのが最も簡単な方法は何ですか?このユースケースは、ビジネスだけではなくHTTPエラーのために使用さロジック等のためのものである - それらは、パイプラインで処理を受けると(404、500、等)。例えばF#WebApiは、識別されたユニオンから正しくフォーマットされたjsonを返します。

通常通りユーザに返さ取得:

type ServiceResult<'a> = { Message:string; Payload:'a } 

type ServiceResponse<'a> = 
    | Success of ServiceResult<'a> 
    | Fail of ServiceResult<string> 

戻り値次のいずれかの

{ 
    "Case": "Fail", 
    "Fields": [ 
    { 
     "Message": "Error performing business logic, your x is not in the y.", 
     "Payload": "I just couldnt do it" 
    } 
    ] 
} 

...か...私はSERVを持っていると思い

{ 
    "Case": "Success", 
    "Fields": [ 
    { 
     "Message": "", 
     "Payload": { "FirstName": "Johnny", "LastName":"Smith" } 
    } 
    ] 
} 

氷の結果は次のように返さ:

{ 
    "Message": "", 
    "Payload": { "FirstName": "Johnny", "LastName":"Smith" } 
} 

...か...

{ 
    "Message": "Error during operation due to spite.", 
    "Payload": "I just couldnt do it" 
} 

私はIdiomaticDuConverterを試してみました: https://gist.github.com/isaacabraham/ba679f285bfd15d2f53e

が、それは仕事をdidntの。私が見た中で最も近いのはMicrosoft.FSharpLu.Jsonですが、パイプラインにプラグインするMediaTypeFormatterはありません。

私はLuを使用して独自のMediaTypeFormatterを作成できますが、もっと簡単な方法(Json.Netの一部のオプションがありません)が必要なように感じます。

正しい方向に向けることができますか?あなたは、単にケースのラベルをスキップして、ネストされたServiceResultにシリアライズを委任するでしょう、あなたのServiceResponseタイプにcustom JSON.NET serializerを書くことができます

答えて

3

あなたが返す表現が正しいデザインであるコーナーケースがあるかもしれませんが、一般的にはこれは良いHTTP APIデザインです。 ASP.NETのWeb APIは、HTTPレスポンスを返すので、

{ 
    "Success": false, 
    "Message": "Error during operation due to spite.", 
    "Payload": "I just couldnt do it" 
} 

を返すの含意は、この値は200 OK応答の一部として返されていることです。これは、HTTPエラー(まだ発生する可能性がある)だけでなく、200 OKが実際に成功を意味すると信じることもできないため、クライアントに余分な負担をかけることになります。

エラーが発生した場合は、the appropriate HTTP status codeを返します。

これもまた問題を解決し、F#コードを簡単に書くことができます。簡単のため

member this.Get() = 
    let result = // produce the result somehow... 
    match result with 
    | Success x -> this.Ok x :> IHttpActionResult 
    | Fail msg -> this.BadRequest msg :> IHttpActionResult 

は、この例では、Failケースに400 Bad Requestを返しますが、この場合は、内部エラーを表す場合、おそらく500 Internal Server Errorがより適切であろう:コントローラでは、基本的にはこのような何かをしたいです。

+0

私の質問がもう少し明確になるように更新しました。成功/失敗はhttp/server/restの失敗ではなく、ビジネスロジックの失敗です。しかし、あなたは私の問題を修正した、私はちょうど結果をIHttpActionResultにキャストする必要があった。 – schmoopy

1

:-)

感謝。

本当の質問はここになぜこの問題がありますか?あなたはすでにレコードに成功/失敗ステータスを持っていますが、DUは追加情報を提供していません。しかも、あなたが持っている設定で、簡単にこのような一見望ましくない状態を表すことができます。

Success <| { Success = false; Message = "necktie"; Payload = "bacon" } 

なぜそれをドロップすると、唯一のレコードの周りに渡し、完全にシリアル化の問題を回避しませんか?

関連する問題