开发者

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 requ开发者_StackOverflow社区est);
}

[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.


Probably has something to do with proxy creation.

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


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜