2011-01-05 110 views
2

以下代碼引發了System.ServiceModel.CommunicationException。它調用名爲登錄一個WCF服務操作返回一個EF4 POCO:從WCF服務操作返回EF4 POCO時引發了CommunicationException

 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,但這意味着它贏得不會被序列化。

如果有人能夠解釋這個問題,我將不勝感激。

下面是服務合同& 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

原來這是使用WCF序列化POCO代理時的一個已知問題。有一個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

我假設的「用戶」類的自定義類?如果是這樣,你需要添加此僅低於ServiceContract特性:

[KnownType(typeof(User))] 

您還需要設置你的[數據成員]和[的ServiceContract]屬性上的用戶類爲好。

+0

用戶類是在我的問題出(會話級以下)。它也用DataContractAttribute裝飾。我會嘗試添加KnownTypeAttribute – 2011-01-06 07:00:30