2011-12-19 9 views
3

私はJSON入力を受け入れ、JSON出力を返すC#での典型的なWCF RESTサービスを持って動作しません:WCF RESTサービス:JSONとWebInvokeと多型が正しく

[ServiceContract] 
public class WCFService 
{ 
    [WebInvoke(Method = "POST", UriTemplate = "register", ResponseFormat = WebMessageFormat.Json)] 
    public BasicResponse RegisterNewUser(UserDTO newUser) 
    { 
     return new BasicResponse() 
     { status = "ERR_USER_NAME" }; 
    } 
} 

public class BasicResponse 
{ 
    public string status { get; set; } 
} 

public class UserDTO 
{ 
    public string username { get; set; } 
    public string authCode { get; set; } 
} 

予想通り、この作品が、私がしたいです通常の実行の場合やエラーが発生した場合には、別のオブジェクトを返す。私は基本的な応答クラスといくつかの継承者を作成しました。今WCF JSONシリアライザがクラッシュし、「400不正な要求」を生成する:

[ServiceContract] 
public class WCFService 
{ 
    [WebInvoke(Method = "POST", UriTemplate = "register", 
     ResponseFormat = WebMessageFormat.Json)] 
    public BasicResponse RegisterNewUser(UserDTO newUser) 
    { 
     return new ErrorResponse() 
     { 
      status = "ERR_USER_NAME", 
      errorMsg = "Invalid user name." 
     }; 
    } 
} 

public class BasicResponse 
{ 
    public string status { get; set; } 
} 

public class ErrorResponse : BasicResponse 
{ 
    public string errorMsg { get; set; } 
} 

public class UserDTO 
{ 
    public string username { get; set; } 
    public string authCode { get; set; } 
} 

私は成功せず[KnownType(typeof(ErrorResponse))][ServiceKnownType(typeof(ErrorResponse))]属性を適用しようとしましたが。多形性をサポートしていることを示すDataContractJsonSerializerのバグのようです。

私のWCF RESTサービスがWebServiceHostFactoryを使用しています。私のWeb.configファイルで

<%@ ServiceHost Language="C#" Debug="true" 
    Service="WCFService" 
    CodeBehind="CryptoCharService.svc.cs" 
    Factory="System.ServiceModel.Activation.WebServiceHostFactory" %> 

私は、標準のHTTPエンドポイントを持っている:

<system.serviceModel> 
    <standardEndpoints> 
    <webHttpEndpoint> 
     <standardEndpoint helpEnabled="true" defaultOutgoingResponseFormat="Json" /> 
    </webHttpEndpoint> 
    </standardEndpoints> 
</system.serviceModel> 

あなたは、これは修正可能だと思いますか?私は回避策を知っています(文字列を返し、手動で出力をシリアル化する)が、なぜこれが機能しないのですか?

答えて

1

私は部分的に説明した問題を克服する方法を見つけました。通常の値(BasicResponseなど)を返す必要がある場合、返すだけです(私のサービスはBasicResponseオブジェクトを返します)。

throw new WebFaultException<ErrorResponse>(
    new ErrorResponse() { errorMsg = "Error occured!" }, 
    HttpStatusCode.NotFound); 

私は、通常のメソッドの戻り値として期待される結果を送信することができます:私はエラー応答を返す必要があるときに、私はまた、JSONとしてシリアライズされ、WCFサービスへのHTTPレスポンスとして送信されWebFaultExceptionとしてそれを返しますこのWebFaultExceptionを通じてエラーが発生した場合の例外的な結果。

0

これは正常に動作する必要があります

[DataContract] 
[KnownType(typeof(ErrorResponse)] 
public class BasicResponse 
{ 
    [DataMember] 
    public string status { get; set; } 
} 

[DataContract] 
public class ErrorResponse : BasicResponse 
{ 
    [DataMember] 
    public string errorMsg { get; set; } 
} 
+1

これらのご提案ありがとうございます。 WCFのコンセプトでは[DataContract]と[DataMember]を使うべきだとわかっていましたが、何時間もの実験の後、DataContractJsonSerializerはこれらの属性を完全に無視してコードから削除しました。あなたのコードは役に立たない。シリアライザはまだクラッシュし、結果は "400 Bad Request"です。シリアライザによってスローされた例外をどのように見ることができますか? –

1

ServiceKnownTypeAttributeが動作します。この1つを試してみてください:

[ServiceKnownType(typeof(ErrorResponse))] 
public BasicResponse RegisterNewUser(UserDTO newUser) 
{ 
    return new ErrorResponse() 
    { 
     status = "ERR_USER_NAME", 
     errorMsg = "Invalid user name." 
    }; 
} 
関連する問題