WCF REST服务:具有JSON和多态的WebInvoke无法正常工作

时间:2011-12-19 22:15:03

标签: c# wcf json polymorphism

我在C#中有一个典型的WCF REST服务,它接受JSON输入并返回JSON输出:

[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 Bad Request":

[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:

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

在我的Web.config中,我有标准的HTTP端点:

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

你认为这是可以解决的吗?我知道一种解决方法(返回字符串并手动序列化输出),但为什么这不起作用?

3 个答案:

答案 0 :(得分:1)

我找到了部分克服所描述问题的方法。当我需要返回一个正常值(例如BasicResponse)时,我只返回它(我的服务返回BasicResponse对象)。当我需要返回错误响应时,我将其作为WebFaultException返回,它也被序列化为JSON并作为HTTP响应发送到WCF服务:

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

现在我可以通过此WebFaultException将预期结果作为普通方法返回值和任何异常结果发送。

答案 1 :(得分:1)

ServiceKnownTypeAttribute适合我。试试这个:

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

答案 2 :(得分: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; }
}