使用DataContract属性在wcf中使用对象数据类型序列化的问题

时间:2011-03-21 08:58:21

标签: asp.net rest wcf

我使用wcf rest starter kit preview 2创建了一个WCF Rest API服务,它根据请求的内容类型自动返回JSON或XML数据。一切正常,但是当我的服务方法返回多个数据类型时,某些方法返回类的对象或类,bool,int或集合类型的集合。所以我计划在所有方法中返回相同的响应。我创建一个新类如下:

 [DataContract(Namespace = "")]
public class ServiceResponse
{
    [DataMember]
    public bool IsError
    { get; set; }

    [DataMember]
    public string ResponseMessage
    { get; set; }

    [DataMember]
    public Object ResponseData
    { get; set; }       

}

和User类如下:

[DataContract(Namespace = "")]
public class User
{
    [DataMember]
    public string UserName 
    { get; set; }

    [DataMember]
    public int UserID
    { get; set; }      

}

在ServiceResponse类中,我声明了一个Object Type属性ResponseData,而我的all方法的返回类型为ServiceResponse。我的问题是,当我设置任何字符串,bool,int类型作为ResponseData时,它被序列化但是当我设置集合类型或另一个类的对象也具有DataContarct属性时,此类未被序列化,请参阅下面的代码:

public ServiceResponse GetUser(int userID)
    {

        User user = getUser(userID); get user data from database

        ServiceResponse response=new ServiceResponse();
        var response = new ServiceResponse
                           {
                               IsError = false,
                               ResponseMessage = string.Empty,
                               ResponseData = user; // Setting Result Data here
                           };
        return response;

    }

当我调用上面的方法(GetUser)时,由于序列化问题,我得到了Null响应,但是下面的代码工作正常

public ServiceResponse TestMethod(string testMessage)
    {


        ServiceResponse response=new ServiceResponse();
        var response = new ServiceResponse
                           {
                               IsError = false,
                               ResponseMessage = string.Empty,
                               ResponseData = testMessage; // Setting Result Data here
                           };
        return response;

    }

任何人都可以帮助我吗?

1 个答案:

答案 0 :(得分:2)

您遇到的问题是由于您在DataContract中将ResponseData声明为Object,但没有告诉WCF哪些类型有效已知类型。您需要明确告诉WCF哪些已知类型对您的服务有效,并且您可以使用ServiceKnownType属性来执行此操作。我已经采用了你的代码并做了一些修改来证明这一点:

DataContracts

[DataContract(Name="ServiceResponse")]
public class ServiceResponse
{
    [DataMember(Name="IsError", Order=1)]
    public bool IsError
    { get; set; }

    [DataMember(Name="ResponseMessage", Order=2)]
    public string ResponseMessage
    { get; set; }

    [DataMember(Name="ResponseData", Order=3)]
    public Object ResponseData
    { get; set; }

}

[DataContract(Name="User")]
public class User
{
    [DataMember(Name="UserName", Order=1, IsRequired=true)]
    public string UserName
    { get; set; }

    [DataMember(Name="UserID", Order=2, IsRequired=true)]
    public int UserID
    { get; set; }

}

[DataContract(Name = "User2")]
public class User2
{
    [DataMember(Name = "UserName", Order = 1, IsRequired = true)]
    public string UserName
    { get; set; }

    [DataMember(Name = "UserID", Order = 2, IsRequired = true)]
    public int UserID
    { get; set; }

}

ServiceCode

[ServiceContract(Namespace = "WebApplication1")]
[ServiceKnownType(typeof(User))]
[ServiceKnownType(typeof(User2))]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1
{
    [OperationContract(Name="GetUser")]
    [WebGet(UriTemplate = "GetUser/{userID}", ResponseFormat = WebMessageFormat.Json)]
    public ServiceResponse GetUser(String userID)
    {
        User theUser = new User()
        {
            UserID=Convert.ToInt32(userID),
            UserName="bob"
        };

        ServiceResponse sr = new ServiceResponse()
        {
            IsError = false,
            ResponseMessage = "",
            ResponseData = theUser
        };

        return sr;
    }

    [OperationContract(Name = "GetUser2")]
    [WebGet(UriTemplate = "GetUser2/{userID}", ResponseFormat = WebMessageFormat.Json)]
    public ServiceResponse GetUser2(String userID)
    {
        User2 theUser = new User2()
        {
            UserID = Convert.ToInt32(userID),
            UserName = "bob"
        };

        ServiceResponse sr = new ServiceResponse()
        {
            IsError = false,
            ResponseMessage = "",
            ResponseData = theUser
        };

        return sr;
    }

}

我做了什么:

  1. 不是必需的,但我在DataContract和成员中添加了一些额外的属性。无论如何,我通常喜欢这样做,所以我只是在那里做强迫症。 :)
  2. 我创建了第二个DataContract来演示ServiceKnownType的使用。
  3. 在服务中,我在服务类上添加了ServiceKnownType属性,说明了可以从我的服务方法返回的类型。
  4. 这就是它。使用ServiceKnownType属性有点难看 - 有一些解决方案可以绕过它(here)。

    如果您还有其他问题,请与我们联系。希望这有帮助!