1

I am new to wcf and I have a simple question.

I use EF with WCF service. WCF service called from WinForms app. I want get simple List from WCF. When i invoke AllVisitors() from wcf test console i get next error:

Failed to invoke the service. Possible causes: The service is offline or inaccessible; the client-side configuration does not match the proxy; the existing proxy is invalid. Refer to the stack trace for more detail. You can try to recover by starting a new proxy, restoring to default configuration, or refreshing the service.

In trace log i see next exaption:

There was an error while trying to serialize parameter http://tempuri.org/:AllVisitorsResult. The InnerException message was 'Type 'System.Data.Entity.DynamicProxies.Visitor_4E7A6F28B7631289C58E0883F6BDF681C78B7180EA3E530CDFE420CAA3C15645' with data contract name Visitor_4E7A6F28B7631289C58E0883F6BDF681C78B7180EA3E530CDFE420CAA3C15645:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types – for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.

Here is my code:

[ServiceContract]
public interface IServiceVisit
{
    [OperationContract]
    [WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedResponse)]
    List<Visitor> AllVisitors();
}

[DataContract]
[KnownType(typeof(Visitor))]
[KnownType(typeof(Visit))]
[KnownType(typeof(ICollection<Visit>))]
public class ServiceVisit : IServiceVisit
{
    public List<Visitor> AllVisitors()
    {
        using (TurnstileDbEntities te = new TurnstileDbEntities())
        {
            return te.Visitors.ToList<Visitor>();
        }
    }
}

The method fails when I try return a List<Visitor>. But the method works perfectly fine when I return a primitive type. Such as int, decimal, string...etc.

Here Visitor and Visit auto generated model:

public partial class Visitor
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Visitor()
    {
        this.Visits = new HashSet<Visit>();
    }

    public int Id { get; set; }
    public int PermitId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string MiddleName { get; set; }
    public bool IsValid { get; set; }
    public System.DateTime RegistrationDate { get; set; }
    public byte[] Picture { get; set; }
             [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Visit> Visits { get; set; }
}

public partial class Visit
{
    public int Id { get; set; }
    public int VisitType { get; set; }
    public System.DateTime VisitDate { get; set; }
    public Nullable<int> Visitor_Id { get; set; }

    public virtual Visitor Visitor { get; set; }
}

I know that List<> is populated with data. And I know that size of data can be big because byte[] Picture contains binary data (images). Also Visitor related to Visit as one to many. As I understood problem is in serialization and in generated dynamic proxies with names like: Visitor_4E7A6F28B7631289C58E0883F6BDF681C78B7180EA3E530CDFE420CAA3C15645. But maybe I'm wrong. So, how can I fix this issue and what am I doing wrong? I found that this issue disscused regulary. But can't find solution for me.

user6408649
  • 1,227
  • 3
  • 16
  • 40
  • 3
    Let me guess: the `Visit`class has a backreference to `Visitor`, creating a circular reference while serializing. Don't simply research this blanket statement of an exception message (it can have _many_ causes); [**enable WCF Tracing to get the actual error**](https://msdn.microsoft.com/en-us/library/ms733025(v=vs.110).aspx). Then use Data Transfer Objects instead of Entity Framework entities to send data from a WCF service. – CodeCaster Jun 01 '16 at 10:02
  • Hi. Yes, the reason of error is not in the returned type. I created a simple testing mehod that return List and this works without errors. "Visitor" linked to "Visit" as one to many. – user6408649 Jun 01 '16 at 10:30
  • 1
    I'm sorry, but that proves that the error _is_ in the returned type. Like I said, enable tracing to find out the actual error. – CodeCaster Jun 01 '16 at 10:33
  • Thank you for advice. I'm enabled wcf tracing and saw that cause of error in Serialization of parameter. As i understand and and read here - https://msdn.microsoft.com/en-us/library/ms730167(v=vs.110).aspx As i understand the KnownType attribute must used. Ok. I added next before ServiceVisit class : [KnownType(typeof(Visitor))] [KnownType(typeof(Visit))] But it is not solved this issue. As i'm see the EF generate proxies like - Visitor_4E7A6F28B7631289C58E0883F6BDF681C78B7180EA3E530CDFE420CAA3C15645. Maybe problemm in this? How can i used KnownType when model generated from EF? – user6408649 Jun 01 '16 at 12:55
  • Please [edit] your question to include all relevant exception messages and what you have tried to resolve them. – CodeCaster Jun 01 '16 at 13:06
  • Can you show the definition of `Visit`? I suspect the problem is the circular reference that @CodeCaster mentioned but you did not answer. – D Stanley Jun 01 '16 at 13:07
  • I changed the description of the issue. Pleace see. – user6408649 Jun 01 '16 at 14:03
  • So, see [DataContractSerializer Error using Entity Framework 4.0 with WCF 4.0](http://stackoverflow.com/questions/3372895/datacontractserializer-error-using-entity-framework-4-0-with-wcf-4-0). But again, don't abuse Entity Framework entity classes as data contracts, because after disabling proxy generation you'll have a circular reference error. – CodeCaster Jun 01 '16 at 14:31
  • 1
    CodeCaster, thank you very much for reply. The one string in the AllVisitors() is a solution for this issue.
    te.Configuration.ProxyCreationEnabled = false;
    But now i can problemm with MaxReceivedMessageSize... But, it is question for another tread. Thanks a lot. Good luck.
    – user6408649 Jun 01 '16 at 15:06

1 Answers1

0

So, solution for this isssue is to set ProxyCreationEnabled = false

    public List<Visitor> AllVisitors()
    {

        using (TurnstileDbEntities te = new TurnstileDbEntities())
        {
            te.Configuration.ProxyCreationEnabled = false;
            return te.Visitors.ToList<Visitor>();
        }
    }
user6408649
  • 1,227
  • 3
  • 16
  • 40