Frage

Der folgende Code stellt eine System.ServiceModel.CommunicationException . Es ruft einen WCF-Dienst Operation namens Anmelden , die eine EF4 POCO zurückgibt:

        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();
        }

Ich habe das Debuggen und die Suche nach Stunden versucht , um herauszufinden, warum dies geschieht und wie es zu beheben. Was ich bisher gefunden habe:

  1. Dies ist wahrscheinlich ein Serialisierung Problem
  2. Wenn ich entfernen die Datamember von der Session Klasse Besitzer Mitglied, die Ausnahme verschwindet, aber das bedeutet, es wird nicht serialisiert werden.

Ich wäre dankbar, wenn jemand etwas Licht ins Dunkel bringen könnte.

Unten ist der Code für den Servicevertrag & POCO Klassen:

[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; }
}
War es hilfreich?

Lösung

Stellt sich heraus, das ist ein bekanntes Problem bei POCO-Proxys mit WCF serialisiert. Es gibt eine MSDN walkthough , die, wie man Arbeit um es erklärt mit System.Data.Objects.ProxyDataContractResolver .

Im Wesentlichen erstellen Sie eine neue Klasse mit dem Namen ApplyDataContractResolverAttribute und es auf die Service-Methoden POCOS Rückkehr:

[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
    }
}

Andere Tipps

Ich bin der Annahme, dass die ‚User‘ Klasse eine benutzerdefinierte Klasse ist? Wenn ja, müssen Sie diese hinzufügen knapp unter dem Servicecontract Attribute:

[KnownType(typeof(User))]

Sie würden auch die Einrichtung benötigen [Datamember] und [Service] Attribute auf der User-Klasse als auch.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top