Как сериализовать вложенные типы в ответе WCF? - PullRequest
2 голосов
/ 21 сентября 2011

Сценарий:

Я нахожусь в процессе создания службы 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.Кажется, что это не может быть сериализовано таким образом.

При поиске возможных решений, но не может найти правильное решение.Я пробовал что-то с KnownTypeAttribute в контракте, а также в классе User, но это не сработало.

Вопросы:

  • Что такоеправильный способ включить свойство Role в класс User?
  • Какие атрибуты нужно добавить, чтобы заставить его работать?
  • Возможные интерфейсы, которые нужно реализовать, чтобы сделать его сериализуемым?

Заранее спасибо за любые ответы!

Обновление # 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, чтобы указать типы, которые не известны статически. '.

Забыл упомянуть в публикации, что классы User и Role используются в Entity Framework 4.1.Не думаю, что это должно быть проблемой, но, видимо, это так.

Ответы [ 4 ]

2 голосов
/ 21 сентября 2011

Возможно, это связано с созданием прокси.

Попробуйте установить следующее: context.ContextOptions.ProxyCreationEnabled = false;

2 голосов
/ 21 сентября 2011

Вам нужно будет сделать User и Role 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 знать, как и что сериализовать. Вот пример смешивания MessageContract и DataContract, как вы делаете в вашем случае, в MSDN здесь: http://msdn.microsoft.com/en-us/library/ff648210.aspx

1 голос
/ 21 сентября 2011
    [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; } 
    } 
0 голосов
/ 21 сентября 2011

Добавление атрибутов datacontract к классам и атрибутам datamember для каждого свойства, которое вы хотите сериализовать

...