none
Unable to serialze member of type TimeZoneInfo

    Question

  • I have a class marked as DataContract that contains a member of a class type that is another DataContract. This used to have no problems being sent across the wire. We recently added a new member to the second data class - the new member is of type TimeZoneInfo. Now when I call a method that returns the top class (which references the 2nd data class, which references TimeZoneInfo) I get an error stating the socket connection has aborted, and when I trace I get this error that seems to be the root cause:

     

    There was an error while trying to serialize parameter http://tempuri.org/:MyMethod. The InnerException message was 'Type 'System.TimeZoneInfo+AdjustmentRule[]' with data contract name 'ArrayOfTimeZoneInfo.AdjustmentRule:http://schemas.datacontract.org/2004/07/System' is not expected. Add any types not known statically to the list of known types

     

    I tried adding all combinations of ServiceKnownType and KnownType to the second class, the service class, the service contract interface. But I still always get this error, so it seems I am not successfully adding what it needs to the known types.

     

    Here is what I'm adding to the service class and contract interface (note I've added all time zone related classes in my attempt to cover all bases):

    [ServiceKnownType(typeof(System.TimeZoneInfo))]

    [ServiceKnownType(typeof(System.TimeZoneInfo.AdjustmentRule))]

    [ServiceKnownType(typeof(System.TimeZoneInfo.AdjustmentRule[]))]

    [ServiceKnownType(typeof(System.TimeZoneInfo.TransitionTime))]

     

    Here is what I'm adding to the the second data class:

    [KnownType(typeof(System.TimeZoneInfo))]

    [KnownType(typeof(System.TimeZoneInfo.AdjustmentRule))]

    [KnownType(typeof(System.TimeZoneInfo.AdjustmentRule[]))]

    [KnownType(typeof(System.TimeZoneInfo.TransitionTime))]

     

    None of this works. Any ideas?

    Wednesday, January 23, 2008 8:18 PM

Answers

  • Hi,

     

    After building a quick repro and debugging, it seems that you need to add all the KnownTypes you added, along with this additional one:

    [KnownType(typeof(System.DayOfWeek))]

     

    That should fix your problem.  That being said, this is quite far from an ideal experience.  Hopefully we can remedy this in a future patch or release.  Sorry for the confusion here, but thanks so much for bringing this issue to our attention.

     

    -- Dave

    Thursday, January 24, 2008 2:30 AM
  • Sorry, my repro (see below) didn't actually define the ServiceContract, but just called into the DCS.  Using ServiceKnownType here is just fine.

    Code Snippet

    class Program

    {

    static void Main(string[] args)

    {

    DataContractSerializer dcs = new DataContractSerializer(typeof(DC1));

    MemoryStream ms = new MemoryStream();

    DC1 someDc1 = new DC1();

    dcs.WriteObject(ms, someDc1);

    ms.Position = 0;

    Console.WriteLine(new StreamReader(ms).ReadToEnd());

    }

    }

     

    [DataContract]

    class DC1

    {

    [DataMember] private DC2 d2 = new DC2();

    }

     

    [DataContract]

    [KnownType(typeof(TimeZoneInfo.AdjustmentRule))]

    [KnownType(typeof(TimeZoneInfo.AdjustmentRule[]))]

    [KnownType(typeof(TimeZoneInfo.TransitionTime))]

    [KnownType(typeof(System.DayOfWeek))]

    class DC2

    {

    [DataMember] private TimeZoneInfo x;

    public DC2()

    {

    // logic to create a TimeZoneInfo with an AdjustmentRule elided

    }

    }

     

     

     

    Regarding your other question, we're investigating whether or not this is simply because of implementing ISerializable, i.e. if it's a bug in the way our Serializer handles such classes.  Since it's not exactly intuitive to have to add 4 - 6 known types just to utilize TimeZoneInfo, we can obviously improve that experience.  We did do some work in .NET 3.5 to ensure that we support DateTimeOffset in a first-class way, but obviously we missed testing some of the other new classes added in 3.5, such as TimeZoneInfo.  If we fix this is in a future release, this won't break your current implementation (adding KnownTypes explicitly), if that's the concern.

     

    Thanks again,

     

    -- Dave

    Thursday, January 24, 2008 6:11 PM

All replies

  • Hi,

     

    After building a quick repro and debugging, it seems that you need to add all the KnownTypes you added, along with this additional one:

    [KnownType(typeof(System.DayOfWeek))]

     

    That should fix your problem.  That being said, this is quite far from an ideal experience.  Hopefully we can remedy this in a future patch or release.  Sorry for the confusion here, but thanks so much for bringing this issue to our attention.

     

    -- Dave

    Thursday, January 24, 2008 2:30 AM
  • System.DayOfWeek was indeed the missing piece of the puzzle. But I had to add it on the service contract using

    [ServiceKnownType(typeof(System.DayOfWeek))]

    not

    [KnownType(typeof(System.DayOfWeek))]

    on the data contract. That didn't work. Should it have worked?

     

    Either way, to summarize the fix (at least what worked for me) for other's benifit, if you need to serialize something that has a member of type TimeZoneInfo, you need to add the following known types to your service contract interface:

    [ServiceContract]

    [ServiceKnownType(typeof(System.TimeZoneInfo))]

    [ServiceKnownType(typeof(System.DayOfWeek))]

    [ServiceKnownType(typeof(System.TimeZoneInfo.AdjustmentRule))]

    [ServiceKnownType(typeof(System.TimeZoneInfo.AdjustmentRule[]))]

    [ServiceKnownType(typeof(System.TimeZoneInfo.TransitionTime))]

    public interface IMyServiceContract

    {....}

     

    One additional question - is this the case because these types weren't marked for serialization properly, and your comment about a remedy would involve a future release where they were marked? If not, could you elaborate a bit.

     

    Thanks

    Thursday, January 24, 2008 5:24 PM
  • Sorry, my repro (see below) didn't actually define the ServiceContract, but just called into the DCS.  Using ServiceKnownType here is just fine.

    Code Snippet

    class Program

    {

    static void Main(string[] args)

    {

    DataContractSerializer dcs = new DataContractSerializer(typeof(DC1));

    MemoryStream ms = new MemoryStream();

    DC1 someDc1 = new DC1();

    dcs.WriteObject(ms, someDc1);

    ms.Position = 0;

    Console.WriteLine(new StreamReader(ms).ReadToEnd());

    }

    }

     

    [DataContract]

    class DC1

    {

    [DataMember] private DC2 d2 = new DC2();

    }

     

    [DataContract]

    [KnownType(typeof(TimeZoneInfo.AdjustmentRule))]

    [KnownType(typeof(TimeZoneInfo.AdjustmentRule[]))]

    [KnownType(typeof(TimeZoneInfo.TransitionTime))]

    [KnownType(typeof(System.DayOfWeek))]

    class DC2

    {

    [DataMember] private TimeZoneInfo x;

    public DC2()

    {

    // logic to create a TimeZoneInfo with an AdjustmentRule elided

    }

    }

     

     

     

    Regarding your other question, we're investigating whether or not this is simply because of implementing ISerializable, i.e. if it's a bug in the way our Serializer handles such classes.  Since it's not exactly intuitive to have to add 4 - 6 known types just to utilize TimeZoneInfo, we can obviously improve that experience.  We did do some work in .NET 3.5 to ensure that we support DateTimeOffset in a first-class way, but obviously we missed testing some of the other new classes added in 3.5, such as TimeZoneInfo.  If we fix this is in a future release, this won't break your current implementation (adding KnownTypes explicitly), if that's the concern.

     

    Thanks again,

     

    -- Dave

    Thursday, January 24, 2008 6:11 PM
  • I think that covers all of my questions. Thanks for the information.

    Thursday, January 24, 2008 6:19 PM
  • I have the same problem and for some reason this recipe doesn't work for me. I'm getting the following: The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:GetZoneResult. The InnerException message was 'Error in line 1 position 939. Element ':AdjustmentRules' contains data of the 'http://schemas.datacontract.org/2004/07/System:ArrayOfTimeZoneInfo.AdjustmentRule' data contract. The deserializer has no knowledge of any type that maps to this contract. Add the type corresponding to 'ArrayOfTimeZoneInfo.AdjustmentRule' to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details. What is wrong?

    Monday, March 02, 2009 11:10 PM
  • I know this question is old, but if anyone runs in to it.  I had to add those lines:

        [ServiceKnownType(typeof(System.TimeZoneInfo))]
        [ServiceKnownType(typeof(System.DayOfWeek))]
        [ServiceKnownType(typeof(System.TimeZoneInfo.AdjustmentRule))]
        [ServiceKnownType(typeof(System.TimeZoneInfo.AdjustmentRule[]))]
        [ServiceKnownType(typeof(System.TimeZoneInfo.TransitionTime))]

    The the interface on the client as well (IxxxxxService)
    Wednesday, January 13, 2010 1:32 AM
  • I am facing exactly the same error when trying to return a List<TimeZoneInfo> from a WCF service method?

    Any luck with finding out with is ArrayOfTimeZoneInfo.AdjustmentRule

    or

    how to resolve this?

    Monday, June 24, 2013 6:09 PM