2016-10-05 3 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" 
    } 
    ] 
} 

... 나 ... 내가 좋아하는 것

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

만 SERV을 가지고 얼음 결과는 같은 반환

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

하지만 일을 일부러. 내가 본 가장 가까운 것은 Microsoft.FSharpLu.Json이지만 파이프 라인에 플러그인 할 MediaTypeFormatter가 없습니다.

나는 Lu를 사용하고 내 자신의 MediaTypeFormatter를 만들 수 있지만 더 쉬운 방법이 있어야한다고 생각합니다 (일부 Json.Net 옵션이 누락되었습니다).

올바른 방향으로 나를 가리킬 수 있습니까? 당신은 단순히 경우 레이블을 생략하고 중첩 된 ServiceResult에 직렬화를 위임 할 것이다 당신의 ServiceResponse 유형에 대한 custom JSON.NET serializer를 작성할 수

답변

3

반환하는 표현이 올바른 디자인 인 경우가있을 수 있지만 일반적으로 은 좋은 HTTP API 디자인이 아닙니다. ASP.NET 웹 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

:-)

감사합니다.

여기 실제 질문은 왜이 문제가있는 것입니까? 기록에 성공/실패 상태가 이미 표시되어있는 경우 하위 사용자는 추가 정보를 제공하지 않습니다. 어떻게 당신이 가지고있는 설정과 함께, 당신은 쉽게 다음과 같이 겉으로는 바람직하지 않은 상태를 나타낼 수, 더 :

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

왜 그냥 모두 직렬화 문제를 방지, 드롭 만 기록 주위에 통과?

관련 문제