如何在WCF响应中序列化嵌套类型?

时间:2011-09-21 12:40:52

标签: c# .net wcf serialization messagecontract

情境:

我正在创建一个公开用户数据的WCF服务。 User的一个实例有一个名为Role的属性。如果我省略此属性,该服务将起作用;如果不省略属性,则服务失败。下面是代码的(非常)简化表示。

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1, EmitConformanceClaims = true)]
[ServiceContract(Name = "IService", Namespace = "http://local/version1/")]
public interface IService : IDisposable
{
   [WebMethod]
   [SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)]
   [OperationContract(Action = "http://local/version1/GetUser")]
   GetUserResponse GetUser(GetUserRequest request);
}

[MessageContract(IsWrapped = true, WrapperName = "GetUserResponse")]
[XmlRoot("GetUserResponse")]
public class GetUserResponse
{
   [XmlElement(ElementName = "User")]
   [MessageBodyMember(Order = 0)]
   public User User { get; set; }
}

public class User
{
   public int UserId { get; set; }

   public string UserName { get; set; }

   public Role Role { get; set; }
}

public class Role
{
   public string Name { get; set; }
}

问题的根源是,在User类中嵌套/嵌入了Role(如何调用它...)。它似乎无法通过这种方式进行序列化。

如果搜索可能的解决方案,但似乎无法找到正确的解决方案。我在合同和User类上尝试过KnownTypeAttribute,但是没有用。

问题:

  • 在User类中包含Role属性的正确方法是什么?
  • 应该在哪里添加哪些属性?
  • 可以实现哪些接口以使其可序列化?

提前感谢您的回复!

更新#1

在建议@CPX之后,我在服务器端创建了额外的测试代码:

using (StringWriter stringWriter = new StringWriter())
{
   XmlSerializer serializer = new XmlSerializer(typeof(GetUserResponse));
   serializer.Serialize(stringWriter, response);
   string result = stringWriter.ToString();
}

这会导致InvalidOperationException,并显示消息“生成XML文档时出错”。此异常具有InvalidOperationException(再次)作为InnerException,并且不期望消息'类型System.Data.Entity.DynamicProxies.User_FAC9CE2C5C9966932C0C37E6677D35437C14CDD08 884AD33C546805E62B7101E。使用XmlInclude或SoapInclude属性指定静态未知的类型。'。

忘了在帖子中提到用户和角色类在Entity Framework 4.1中使用。没想到应该是一个问题,但显然确实如此。

4 个答案:

答案 0 :(得分:2)

您需要像这样制作UserRole DataContracts:

[DataContract]
public class User
{
   [DataMember]
   public int UserId { get; set; }

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

   [DataMember]
   public Role Role { get; set; }
}

[DataContract]
public class Role
{
   [DataMember]
   public string Name { get; set; }
}

这让WCF知道序列化的方式和内容。正如您所做的那样,在MSDN上有一个混合MessageContractDataContract的示例:http://msdn.microsoft.com/en-us/library/ff648210.aspx

答案 1 :(得分:2)

可能与代理创建有关。

尝试设置以下内容: context.ContextOptions.ProxyCreationEnabled = false;

答案 2 :(得分:1)

    [DataContract]  
    public class User {   

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

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

    [DataMember]    
    public Role role { get; set; } }  

    [DataContract] 
    public class Role
    {
       [DataMember]
       public string Name { get; set; } 
    } 

答案 3 :(得分:0)

将datacontract属性添加到要序列化的每个属性的classes和datamember属性