【问题标题】:WCF REST Service: WebInvoke with JSON and polymorphism does not work correctlyWCF REST 服务:带有 JSON 和多态性的 WebInvoke 无法正常工作
【发布时间】:2011-12-19 22:15:02
【问题描述】:

我在 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>

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

【问题讨论】:

    标签: c# wcf json polymorphism


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

      ServiceKnownTypeAttribute 对我有用。试试这个:

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

      【讨论】:

        【解决方案3】:

        这应该可以正常工作:

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

        【讨论】:

        • 感谢这些建议。我知道按照 WCF 中的概念,我应该使用 [DataContract] 和 [DataMember],但经过数小时的实验后,我发现 DataContractJsonSerializer 完全忽略了这些属性,因此我将它们从代码中删除。您的代码没有帮助。序列化程序仍然崩溃,结果仍然是“400 Bad Request”。你知道我怎样才能看到序列化程序抛出的异常吗?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-08
        • 1970-01-01
        • 2020-05-08
        • 2022-01-13
        相关资源
        最近更新 更多