Question

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:

  • What is the proper way to include the Role property on the User class?
  • Which attributes should be added where to make it work?
  • Possible interfaces to be implemented to make it serializable?

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.

Was it helpful?

Solution

Probably has something to do with proxy creation.

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

OTHER TIPS

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

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

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top