How to fix MaxItemsInObjectGraph error?

I have a RESTful WCF service and I am getting the following error: Maximum number of items that can be serialized or deserialized in an object graph is '65536'. Change the object graph or increase the MaxItemsInObjectGraph quota.

I thought I had resolved this but apparently not. Here is my code:

I use a .SVC file that uses a custom factory like this:

<%@ ServiceHost Language="C#" Debug="true" Service="myService" Factory="myCustomWebServiceHostFactory" %>

Here is the code for the custom factory

public class myCustomWebServiceHost : WebServiceHost
{
    public myCustomWebServiceHost()
    {
    }

    public myCustomWebServiceHost(object singletonInstance, params Uri[] baseAddresses)
        : base(singletonInstance, baseAddresses)
    {
    }

    public myCustomWebServiceHost(Type serviceType, params Uri[] baseAddresses)
        : base(serviceType, baseAddresses)
    {
    }

    protected override void OnOpening()
    {
        foreach (var endpoint in Description.Endpoints)
        {
            var binding = endpoint.Binding as WebHttpBinding;
            if (binding != null)
            {
                const int fiveMegaBytes = 5242880;
                binding.MaxReceivedMessageSize = fiveMegaBytes;
                binding.MaxBufferSize = fiveMegaBytes;
                binding.MaxBufferPoolSize = fiveMegaBytes;
            }
        }
        base.OnOpening();
    }
}

class myCustomWebServiceHostFactory : WebServiceHostFactory
{
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
        return new myCustomWebServiceHost(serviceType, baseAddresses);
    }
}

Service:

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceContract]
[ServiceBehavior(MaxItemsInObjectGraph = int.MaxValue)]
public class myService
{
...service implementation code goes here
}

Client:

public class myClient
{
    WebChannelFactory<IMyService> cf;
    IMyService channel;

    public myClient()
    {
        WebHttpBinding _binding = new WebHttpBinding();
        _binding.MaxBufferPoolSize = 5000000;
        _binding.MaxBufferSize = 5000000;
        _binding.MaxReceivedMessageSize = 5000000;
        _binding.TransferMode = TransferMode.Streamed;
        _binding.ReceiveTimeout = new TimeSpan(0, 0, 30);
        _binding.ReaderQuotas.MaxArrayLength = 5000000;
        Uri _uri = new Uri("http://myserviceurl");
        cf = new WebChannelFactory<IMyService>(_binding, _uri);
        channel = cf.CreateChannel();
        foreach (OperationDescription op in cf.Endpoint.Contract.Operations)
        {
            var dataContractBehavior = op.Behaviors.Find<DataContractSerializerOperationBehavior>();
            if (dataContractBehavior != null)
            {
                dataContractBehavior.MaxItemsInObjectGraph = int.MaxValue;
            }
        }
    }
        ...client implementation code goes here
}

UPDATE: I have done a little troubleshooting. It seems that the serialization part is working fine on the server. I am able to do a GET from a browser and I receive back all of the data in XML format. So that is working fine. It seems to be the deserialization part that is causing the error. If you look above in the code for myClient you will see how I am attempting to set the MaxItemsInObjectGraph property for the DataContractSerializer behavior. Am I doing this correctly?

Answers


I figured it out!!! My client code was wrong. I was setting the MaxItemsInObjectGraph after I had already created my channel. So the MaxItemInObjectGraph property had no effect on the already created channel. (This WCF stuff is so confusing to me - I am usually just copying and pasting code without really knowing what I am doing) Here is the corrected code:

        WebHttpBinding _binding = new WebHttpBinding();
        _binding.MaxBufferPoolSize = 5000000;
        _binding.MaxBufferSize = 5000000;
        _binding.MaxReceivedMessageSize = 5000000;
        _binding.TransferMode = TransferMode.Streamed;
        _binding.ReceiveTimeout = new TimeSpan(0, 0, 30);
        _binding.ReaderQuotas.MaxArrayLength = 5000000;
        Uri _uri = new Uri(http://myserviceurl);
        cf = new WebChannelFactory<IMyService>(_binding, _uri);
        foreach (OperationDescription op in cf.Endpoint.Contract.Operations)
        {
            var dataContractBehavior = op.Behaviors.Find<DataContractSerializerOperationBehavior>();
            if (dataContractBehavior != null)
            {
                dataContractBehavior.MaxItemsInObjectGraph = int.MaxValue;
            }
        }
        channel = cf.CreateChannel();

You need to set the MaxItemsInObjectGraph on the dataContractSerializer using a behavior on both the client and service. See here for an example.


On the client side, another way to achieve this is to create a custom IEndPointBehavior implementation - refer to http://canbilgin.wordpress.com/2010/06/25/how-to-set-maxitemsinobjectgraph-programmatically-for-client/.

This is particularly useful when implementing a client with the Windsor WcfFacility

public class ReaderQuotaExtension : IEndpointBehavior
{
    #region Implementation of IEndpointBehavior

    public void Validate(ServiceEndpoint endpoint)
    {
    }

    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
        ModifyDataContractSerializerBehavior(endpoint);
    }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        ModifyDataContractSerializerBehavior(endpoint);
    }

    #endregion

    private static void ModifyDataContractSerializerBehavior(ServiceEndpoint endpoint)
    {
        foreach (var behavior in endpoint.Contract.Operations.Select(operation => operation.Behaviors.Find<DataContractSerializerOperationBehavior>()))
        {
            behavior.MaxItemsInObjectGraph = 2147483647;
        }
    }

You are returning a generic list or an array which has a size of more than 65536. in your queries, using a select top 60000 or not adding more than 60k elements will solve your problem.


Need Your Help

Is it possible to have a one line each block in Ruby?

ruby

Is there a one-line method of writing this each block in Ruby?

Font looks blurry after translate in Chrome

html css css3 google-chrome chromium

EDIT 2016-07-04(Since this question is getting popular): This is a bug in Chrome. Developers are actively working on a fix.