2

以下代码引发System.ServiceModel.CommunicationException。它正在调用一个名为Login的 WCF 服务操作,该操作返回一个 EF4 POCO:

        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. 当我从Session类的Owner成员中删除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; }
}
4

2 回答 2

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
    }
}
于 2011-01-06T08:43:55.680 回答
0

我假设“用户”类是自定义类?如果是这样,您需要在 ServiceContract 属性下方添加它:

[KnownType(typeof(User))]

您还需要在 User 类上设置 [DataMember] 和 [ServiceContract] 属性。

于 2011-01-05T16:17:11.603 回答