2011-01-05 5 views
2

Следующий код вызывает System.ServiceModel.CommunicationException. Это вызов операции службы WCF под названием Войти возвращающий Ef4 ПОКО:CommunicationException, возникающий при возврате EF4 POCO из работы службы WCF

 var client = new AuthServiceReference.AuthServiceClient(); 

     try 
     { 
      Console.Write("Trying to logon..."); 
      var session = client.Login("user", "password"); // throws CommunicationException 
      Console.WriteLine("done!"); 
      Console.WriteLine("Session ID: {0}. Expires {1}", 
       session.Id, session.UtcExpires.ToLocalTime()); 
     } 
     finally 
     { 
      client.Close(); 
     } 

Я отладки & поиска в течение нескольких часов, пытаясь выяснить, почему это происходит &, как это исправить. То, что я нашел до сих пор:

  1. Это, вероятно, проблема сериализации
  2. Когда я удалить DataMemberAttribute от Владелец члена в Session класса, исключение исчезает, но это означает, что он выиграл Серийно.

Я был бы признателен, если кто-нибудь сможет пролить свет на этот вопрос.

Ниже приведен код для классов обслуживания контракта & POCO:

[ServiceContract] 
public interface IAuthService 
{ 
    [OperationContract] 
    Session Login(string username, string passwordHash); 

    [OperationContract] 
    void Logout(Guid sessionId); 
} 

[DataContract] 
public class Session 
{ 
    [DataMember] 
    public Guid Id { get; set; } 

    [DataMember] 
    public DateTime UtcCreated { get; set; } 

    [DataMember] 
    public DateTime UtcExpires { get; set; } 

    [DataMember] // serializes correctly if commented out 
    public virtual User Owner { get; set; } 

    public static Session Create(User owner) 
    { 
     return new Session 
     { 
      Owner = owner, 
      Id = Guid.NewGuid(), 
      UtcCreated = DateTime.UtcNow, 
      UtcExpires = DateTime.UtcNow.AddDays(1) 
     }; 
    } 
} 

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

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

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

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

    [DataMember] 
    public bool IsContributor { get; set; } 

    [DataMember] 
    public bool IsConfirmed { get; set; } 

    [DataMember] 
    public bool IsAdmin { get; set; } 

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

    [DataMember] 
    public virtual ICollection<Post> Posts { get; set; } 

    [DataMember] 
    public virtual ICollection<Comment> Comments { get; set; } 
} 

ответ

3

Оказывается, это известная проблема при сериализации прокси-серверов POCO с WCF. Существует MSDN walkthough, в котором объясняется, как обойти его, используя System.Data.Objects.ProxyDataContractResolver.

По сути, вы создаете новый класс ApplyDataContractResolverAttribute и применить его к методам обслуживания возвращения Pocos:

[ServiceContract] 
public interface IAuthService 
{ 
    [OperationContract] 
    [ApplyDataContractResolver] 
    Session Login(string username, string passwordHash); 
} 

using System; 
using System.Data.Objects; 
using System.ServiceModel.Channels; 
using System.ServiceModel.Description; 
using System.ServiceModel.Dispatcher; 

namespace WcfExampleBlog.Services 
{ 
    public class ApplyDataContractResolverAttribute : Attribute, IOperationBehavior 
    { 
     #region IOperationBehavior Members 

     public void AddBindingParameters(OperationDescription description, BindingParameterCollection parameters) 
     { 
     } 

     public void ApplyClientBehavior(OperationDescription description, ClientOperation proxy) 
     { 
      var dataContractSerializerOperationBehavior = 
       description.Behaviors.Find<DataContractSerializerOperationBehavior>(); 
      dataContractSerializerOperationBehavior.DataContractResolver = 
       new ProxyDataContractResolver(); 
     } 

     public void ApplyDispatchBehavior(OperationDescription description, DispatchOperation dispatch) 
     { 
      var dataContractSerializerOperationBehavior = 
       description.Behaviors.Find<DataContractSerializerOperationBehavior>(); 
      dataContractSerializerOperationBehavior.DataContractResolver = 
       new ProxyDataContractResolver(); 
     } 

     public void Validate(OperationDescription description) 
     { 
      // Do validation. 
     } 

     #endregion 
    } 
} 
0

Я предполагаю, что класс «User» является пользовательским классом? Если да, то вам нужно добавить это чуть ниже атрибута ServiceContract:

[KnownType(typeof(User))] 

Кроме того, необходимо будет настроить ваши [DataMember] и [ServiceContract] атрибуты в классе User, а также.

+0

Класс пользователя показан на мой вопрос (ниже класса Session). Он также украшен DataContractAttribute. Я попробую добавить KnownTypeAttribute –

Смежные вопросы