1

Given the following DataContract:

[DataContract]
public class GetGameSessionHistory : ValueBaseCasinoIT
{
    [DataMember]
    public GameSession[] GameSessions => GameSessionsValue.ToArray<GameSession>();

    public IEnumerable<GameSession> GameSessionsValue { get; set; }
}

I still get the error message that GetGameSessionHistory is not serializable due to the IEnumerable interface.

System.NotSupportedException: Cannot serialize member GetGameSessionHistory.GameSessionsValue of type System.Collections.Generic.IEnumerable`1[[GameSession, Common, Version=3.45.0.11, Culture=neutral, PublicKeyToken=null]] because it is an interface.

I also tried the approach of removing the overall [DataContract] attribute and specifically ignore the affected members with [IgnoreDataMember]. But unfortunately that leads to the same outcome.

Update 1

The Lambda Expression in the given code was just a step i planned to do. The problem remains the same when using the following DataContract:

[DataContract]
public class GetGameSessionHistory : ValueBaseCasinoIT
{
    [DataMember]
    public GameSession[] GameSessions { get; set; }

    public IEnumerable<GameSession> GameSessionsValue { get; set; }
}

When removing the IEnumerable the message disappears. So the problem can't come from the GameSession type.

Currently I'm using the XmlSerializer.

The Data is used in the following Service:

IAdapterService:

[ServiceContract, XmlSerializerFormat(Style = OperationFormatStyle.Rpc, Use = OperationFormatUse.Encoded), DispatchByBodyBehavior]
public interface IAdapterService
{
    [OperationContract(Name = "GetGameSessionHistoryRequest", Action = ""), DispatchBodyElement("GetGameSessionHistoryRequest", "...")]
    GetGameSessionHistory GetGameSessionHistory(AuthenticationToken authenticationToken, string playerId, DateTime fromDate, DateTime toDate);
}

AdapterService:

[SoapDocumentService(SoapBindingUse.Literal, RoutingStyle = SoapServiceRoutingStyle.RequestElement)]
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]
public class AdapterService : IAdapterService
{
    public GetGameSessionHistory GetGameSessionHistory(AuthenticationToken authenticationToken, string playerId, DateTime fromDate, DateTime toDate)
    { ... }
}

Web.config:

<basicHttpBinding>
    <binding name="SoapBinding">
        <security mode="None"/>
        <readerQuotas maxDepth="4000" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="32768"/>
    </binding>
</basicHttpBinding>

<service name="...svc.AdapterService" behaviorConfiguration="svcBehavior" >
    <endpoint binding="basicHttpBinding" bindingConfiguration="SoapBinding" contract="...IAdapterService" name="AdapterSoapBinding" behaviorConfiguration="withMessageInspector"/>
</service>

What else could cause this problem?

chrsi
  • 992
  • 9
  • 24
  • Well, other things aside: it isn't going to able to *deserialize* `GameSessions` – Marc Gravell Jul 04 '16 at 09:40
  • Related : http://stackoverflow.com/questions/2068897/cannot-serialize-parameter-of-type-system-linq-enumerable-when-using-wcf –  Jul 04 '16 at 09:43
  • 2
    can you confirm **exactly** which serializer WCF is configured to use? there is `DataContractSerializer` and `NetDataContractSerializer`, which can be selected by configuration. (edit: although I tried `NetDataContractSerializer` in the code in my answer, and it still worked fine) – Marc Gravell Jul 04 '16 at 09:48

2 Answers2

1

If I try your code, serialization works fine; deserialization fails with:

System.Runtime.Serialization.SerializationException: The get-only collection of type 'GameSession[]' returned a null value. The input stream contains collection items which cannot be added if the instance is null. Consider initializing the collection in the getter.

which is what I would expect, because it has no way of assigning a value to GameSessions. If I add a set... everything works. Here's the fully working code:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;

class Program
{
    static void Main()
    {
        var ser = new DataContractSerializer(typeof(GetGameSessionHistory));
        using (var ms = new MemoryStream())
        {
            var orig = new GetGameSessionHistory { GameSessionsValue =
                new List<GameSession>() { new GameSession { } } };
            ser.WriteObject(ms, orig);
            ms.Position = 0;
            var clone = (GetGameSessionHistory)ser.ReadObject(ms);
            Console.WriteLine(clone?.GameSessionsValue.Count()); // prints 1
        }
    }

}
[DataContract]
public class GetGameSessionHistory : ValueBaseCasinoIT
{
    [DataMember]
    public GameSession[] GameSessions
    {
        get { return GameSessionsValue?.ToArray(); }
        set { GameSessionsValue = value; }
    }
    //[DataMember] // original version; fails with The get-only collection of type
                   // 'GameSession[]' returned a null value.
    //public GameSession[] GameSessions => GameSessionsValue?.ToArray<GameSession>();

    public IEnumerable<GameSession> GameSessionsValue { get; set; }
}

[DataContract]
public class ValueBaseCasinoIT
{
}

[DataContract]
public class GameSession
{
}

I think you might need to add more info to help us identify the problem, because... it basically works.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • thanks for your hint, I will consider it afterwards. please mind my new update. hopefully there's now enough info for the underlying issue. – chrsi Jul 04 '16 at 10:37
0

Problem found: I was using the XmlSerializer (IAdapterService is attributed with [XmlSerializerFormat]) which causes all public properties to be serialized.

The DataContractSerializer (XmlObjectSerializer) would consider the [DataMember] attributes for the serialization process, while the XmlSerializer simply ignores them.

The question remains, why the [XmlIgnore] attribute wasn't working as well.

chrsi
  • 992
  • 9
  • 24