4

I cant handle one simple (as i thought) task. I have 2 POCO classes which I want to send throuh WCF service:

Estate class withc derive from Advert class, and Locations whitch are related to adverts (adverts belong to some locations Many to many relationship)

Here are my data contract:

[DataContract]
[KnownType(typeof(Location))]
[KnownType(typeof(Estate))]
public abstract class Advert
{
    [DataMember]
    public int ID { get; set; }
    [DataMember]
    public decimal? Price { get; set; }
    [DataMember]
    public byte FromAgent { get; set; }
    [DataMember]
    public DateTime Date { get; set; }

    [DataMember]
    public virtual ICollection<Url> Urls { get; set; }
    [DataMember]
    public virtual ICollection<Location> Locations { get; set; }
    [DataMember]
    public virtual ICollection<PhoneNumber> PhoneNumbers { get; set; } 
}

[KnownType(typeof(Location))]
[DataContract]
public class Estate : Advert
{
    [DataMember]
    public byte OfferType { get; set; }

    [DataMember]
    public byte EstateType { get; set; }

    [DataMember]
    public byte MarketType { get; set; }

    [DataMember]
    public int? Area { get; set; }

    [DataMember]
    public byte? Rooms { get; set; }
}


[DataContract]
public class Location
{
    [DataMember]
    public int ID { get; set; }
    [DataMember]
    public byte Type { get; set; }
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public string NamePrefix { get; set; }
    [DataMember]
    public string Feature { get; set; }
    [DataMember]
    public int NumberOfEstates { get; set; }

    [DataMember]
    public virtual ICollection<Location> ParentLocations { get; set; }
    [DataMember]
    public virtual ICollection<Advert> Adverts { get; set; }
}

My Service interface:

    [OperationContract]
    [ServiceKnownType(typeof(Location))]
    IEnumerable<Estate> GetEstates(EstateFilter filter);

Its implementation:

    public IEnumerable<Estate> GetEstates(EstateFilter filter)
    {
        return EstateProcesses.GetEstates(filter);
    }

And in business layer:

    public static List<Estate> GetEstates(EstateFilter filter)
    {
        List<Estate> estates;

        if (filter==null) filter = new EstateFilter();

        using (var ctx = new Database.Context())
        {
            estates = (from e in ctx.Adverts.OfType<Estate>()
                       where
                              (filter.ID == null || e.ID == filter.ID)
                              && (filter.DateFrom == null || e.Date >= filter.DateFrom)
                              && (filter.DateTo == null || e.Date <= filter.DateTo)
                              && (filter.PriceFrom == null || e.Price >= filter.PriceFrom)
                              && (filter.PriceTo == null || e.Price <= filter.PriceTo)
                              && (filter.FromAgent == null || e.FromAgent == filter.FromAgent)
                              && (filter.LocationID == null || e.Locations.Any(l => l.ID == filter.LocationID))
                              && (filter.PhoneNumber == null || e.PhoneNumbers.Any(p => p.Number == filter.PhoneNumber))
                              && (filter.Url == null || e.Urls.Any(u => u.Address == filter.Url))
                          select e).ToList();
            foreach (var estate in estates)
            {
                ctx.LoadProperty(estate, e => e.Locations);
            }
        }

        return estates;
    }

Exception i obtain is in Polish:

Połączenie gniazda zostało przerwane. Mogło to być spowodowane błędnym przetwarzaniem komunikatu, przekroczeniem limitu czasu odbioru przez zdalny host lub problemem z zasobami sieciowymi podległej sieci. Limit czasu lokalnego gniazda wynosi „00:00:59.9929996”.

In english it would go like:

The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was „00:00:59.9929996”.

Server stack trace is following:

Server stack trace: 
   w System.ServiceModel.Channels.SocketConnection.ReadCore(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout, Boolean closing)
   w System.ServiceModel.Channels.SocketConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout)
   w System.ServiceModel.Channels.DelegatingConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout)
   w System.ServiceModel.Channels.SessionConnectionReader.Receive(TimeSpan timeout)
   w System.ServiceModel.Channels.SynchronizedMessageSource.Receive(TimeSpan timeout)
   w System.ServiceModel.Channels.FramingDuplexSessionChannel.Receive(TimeSpan timeout)
   w System.ServiceModel.Channels.FramingDuplexSessionChannel.TryReceive(TimeSpan timeout, Message& message)
   w System.ServiceModel.Dispatcher.DuplexChannelBinder.Request(Message message, TimeSpan timeout)
   w System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   w System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   w System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: 
   w System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   w System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   w IService.GetEstates(EstateFilter filter)
   w ServiceClient.GetEstates(EstateFilter filter)

i also use this classes as POCO classes in EF.

and here is the problem: if i send estate without loading locations it works just fine. but if i want to send estate with locations WCFHostClient throws an error.

And a question: How to send through WCF IEnumerable of Estate where each Estate contain ICollection of Location?

  • 2
    You wrote this question and decided it wouldn't be helpful to actually tell us what the error is? – Kirk Woll May 03 '12 at 17:34
  • You need to tell us what the error is and also check to see if an error is occurring on the server. Is it related to the size of the message? You could try checking if [increasing the message size](http://stackoverflow.com/questions/1343628/wcf-maxreceivedmessagesize-not-being-read-from-config) allowed helps. (the actual error you posted doesn't really tell us much) – Sam Holder May 03 '12 at 17:52
  • perhaps you could post the actual exception message and possible your best guess at a translation of it? – Sam Holder May 03 '12 at 17:59
  • 1
    Enable WCF tracing (http://msdn.microsoft.com/en-us/library/ms732023.aspx) this way you will find a "better" exception – Rico Suter May 03 '12 at 18:02
  • Added english translation for an error. Enabling WCF tracing doest change an error message. – user1301357 May 03 '12 at 18:10
  • @user1301357 based on your exception it looks like you need to increase the timeout, as it seems that your service call is taking longer than 1 minute to return. try [setting the timeout](http://stackoverflow.com/questions/424358/increasing-the-timeout-value-in-a-wcf-service) to 10 mins and see if that fixes the issue. If something went wrong on the server you would expect a different exception – Sam Holder May 03 '12 at 18:10
  • It cant take more than a minute. Its really small database. If i do the same action it standard program instead of WCF it takes less than a 1 second. – user1301357 May 03 '12 at 18:12
  • can you attach a debugger to the server and check there is no exception when you call from the client? – Sam Holder May 03 '12 at 18:14
  • there is no exception. debugger already attached – user1301357 May 03 '12 at 18:16
  • do you have circular dependencies in your model? The DataContractSerializer cannot serialize something with circular dependencies, at least not be default if I recall. It looks like you could have Estate.Adverts containing Locations which contain the same Adverts? – Sam Holder May 03 '12 at 18:23
  • commenting [DataMember] in filds contining lists in Location AND in Advert doesn't help ;( – user1301357 May 03 '12 at 18:50
  • turn on tracing for both system datamodel namespace and system serialization, something must be going wrong somewhere. – Sam Holder May 03 '12 at 19:23
  • 2
    Your service is generating an exception. in order to find you what is the exception you have to either turn on wcf tracing which will product .trace files which can be read by built it tool in windows or you can turn on the tracing in the web config ( ) and see the exception by entering the service's url followed by /trace.axd (for example http://myserviceurl.com/trace.axd) – Koby Mizrahy May 03 '12 at 22:03

1 Answers1

0

The object tree contains lots of opportunities for circular dependencies. Try adding this to Location

[DataContract(IsReference=true]
public class Location

You might have to add this to the Advert class as well (Advert -> Location -> advert). You might want to think about the object tree to minimize the payload.

DaveK
  • 41
  • 2