2011-01-05 6 views
2

次のコードでは、System.ServiceModel.CommunicationExceptionが発生します。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(); 
     } 

私はが、これはそれを修正する方法を&なぜ起こるかを見つけるためにしようと時間を探し&をデバッグしてきた:それはEF4 POCOを返しログイン呼ばれるWCFサービス操作を呼び出します。私がこれまでに見つけた:

  1. は、これは私がセッションクラスの所有者メンバーからDataMemberAttributeを削除すると、例外が消えますが、これはそれが勝った意味おそらく、シリアル化問題
  2. ですシリアライズしないでください。

誰かがこの問題を明らかにしてくれればと感謝します。

以下

は、サービス契約& 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プロキシをシリアル化する際の既知の問題です。 System.Data.Objects.ProxyDataContractResolverを使用して回避する方法を説明するMSDN walkthoughがあります。

基本的に、あなたはApplyDataContractResolverAttributeと呼ばれる新しいクラスを作成して返すサービスメソッドに適用POCOS:Userクラスは、私の質問に

[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属性の下にこれを追加する必要があります:あなたはまた、同様にUserクラス上の設定にあなたの[DataMemberプロパティ]および[のServiceContract]属性が必要になります

[KnownType(typeof(User))] 

+0

を示している(Sessionクラス以下)。また、DataContractAttributeで飾られています。私はKnownTypeAttributeを追加しようとします –

関連する問題