DataContractSerializer – MaxItemsInObjectGraph exceeded exception
Simple Self Reference
Consider the following class – a Person contains a list of Children – who are also Persons. So, Person references Person inside itself. This is a self-reference.
public Person(string firstName, string lastName, Person parent)
{
FirstName = firstName;
LastName = lastName;
// this is a SELF reference - A reference to a member (children, who are also PERSONS) in the same object (person)
Children = new List<Person>();
Parent = parent;
}
In older WCF, this would throw an exception if you tried to serialize the class above using DataContractSerializer (maxItemsInObjectGraphExceeded).
// In older WCF, this would throw an exception during serialization (due to the self reference)
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
[DataMember]
public List<Person> Children { get; set; }
[DataMember]
public Person Parent { get; set; }
However, now WCF will actually check if you have a self-reference and throw a meaningful exception as shown below.
An exception occured: Object graph for type 'DataContractSerializerExample.Perso
n' contains cycles and cannot be serialized if reference tracking is disabled.
Solution
All you need to do is mark the Person object appropriately. You need to specify that it has a circular reference inside it. This is done by using the IsReference property of datacontract as shown below.
[DataContract(IsReference = true)]
public class Person
{
public Person(string firstName, string lastName, Person parent)
{
FirstName = firstName;
LastName = lastName;
// this is a SELF reference - A reference to a member (children, who are also PERSONS) in the same object (person)
Children = new List<Person>();
Parent = parent;
}
// In older WCF, this would throw an exception during serialization (due to the self reference)
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
[DataMember]
public List<Person> Children { get; set; }
[DataMember]
public Person Parent { get; set; }
}
[DataContract(IsReference = true)]
public class Person
{
public Person(string firstName, string lastName, Person parent)
{
FirstName = firstName;
LastName = lastName;
// this is a SELF reference - A reference to a member (children, who are also PERSONS) in the same object (person)
Children = new List<Person>();
Parent = parent;
}
// In older WCF, this would throw an exception during serialization (due to the self reference)
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
[DataMember]
public List<Person> Children { get; set; }
[DataMember]
public Person Parent { get; set; }
}
Summary
The DataContractSerializer is what makes WCF stand apart from old style ASMX web services. The speed and efficiency of this serializer itself make it worth upgrading from ASMX to WCF. Even though the DataContractSerializer is equipped to handle up to 2,147,483,647 items in its object graph, one may still see a ‘max items exceeded’ exception. Usually, this is caused by a circular reference within your object definition. If you have such a circular reference, try and use the IsReference = true property of the DataContract attribute as shown above. If it is simply a matter of a large data object (certain composite objects), you may just need to tweak the default size of the maxItems in web.config.
Appendix – Web.Config Setting for maxItemsInObjectGraph in dataContractSerializer
One can modify the max items in the web.config setting for datacontractserializer (A good explanation of what constitutes an Item in the graph is found here.)
The default Value is 65536. The max Value is max value of Int32 – 2,147,483,647.
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
Leave a Reply