Herman Cordes
Herman Cordes

Reputation: 4976

How to serialize nested types in WCF response?

Scenario:

I'm in the process of creating a WCF service that exposes user data. An instance of User has a property called Role. If I omit this property, the service works; if don't omit the property, the service fails. Below is a (very) simplified representation of the code.

[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; }
}

The root of the problem is that the Role is nested/embedded (how do you call it...) in the User class. It seems that it can't be serialzed this way.

If searched on possible solutions, but can't seem to find the right solution. I've tried something with KnownTypeAttribute on the contract as well as the User class, but that didn't work.

Questions:

Thanks in advance for any replies!

Update #1

After suggestions of @CPX, I created additional test code on the server side:

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

This results in an InvalidOperationException with message 'There was an error generating the XML Document'. This exception has an InvalidOperationException (again) as InnerException, with message 'The type System.Data.Entity.DynamicProxies.User_FAC9CE2C5C9966932C0C37E6677D35437C14CDD08‌​884AD33C546805E62B7101E was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.'.

Forgot to mention in the post, that the User and Role classes are used within Entity Framework 4.1. Didn't guess should be a problem, but apparently it does.

Upvotes: 2

Views: 4842

Answers (4)

Gregory Nozik
Gregory Nozik

Reputation: 3372

    [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; } 
    } 

Upvotes: 1

Peanutbag
Peanutbag

Reputation: 277

Probably has something to do with proxy creation.

Try setting the following: context.ContextOptions.ProxyCreationEnabled = false;

Upvotes: 2

CodingWithSpike
CodingWithSpike

Reputation: 43738

You will need to make User and Role DataContracts like this:

[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; }
}

This lets WCF know how and what to serialize. There is an example of mixing MessageContract and DataContract, as you are doing in your case, on MSDN here: http://msdn.microsoft.com/en-us/library/ff648210.aspx

Upvotes: 2

tam
tam

Reputation: 1583

Add datacontract attributes to the classes and datamember attributes to each property you want to serialize

Upvotes: 0

Related Questions