How to fix MaxItemsInObjectGraph error?

I have a RESTful WCF service and I get the following error: The maximum number of elements that can be serialized or deserialized in the object graph is "65536". Change the object graph or increase the quota of MaxItemsInObjectGraph.

I thought I solved it, but apparently not. Here is my code:

I am using a .SVC file that uses a custom factory as follows:

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

Here is the code for 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); } } 

Services:

 [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 did a bit of work. It seems that serialization partially works on the server. I can make a GET from a browser, and I get back all the data in XML format. So this is normal. This seems to be part of the deserialization that is causing the error. If you look above in the myClient code, you will see how I try to set the MaxItemsInObjectGraph property for the DataContractSerializer behavior. Am I doing it right?

+11
source share
4 answers

I get it!!! My client code was wrong. I installed MaxItemsInObjectGraph after I already created my channel. Thus, the MaxItemInObjectGraph property did not affect the already created channel. (This WCF stuff is so confusing for me - I usually just copy and paste the code without knowing what I'm 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(); 
+23
source

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

+4
source

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

This is especially useful when implementing a client using 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; } } 
0
source

You return a general list or an array whose size exceeds 65536. In your queries, using the selected top of 60,000 or not adding more than 60 thousand elements, you will solve your problem.

0
source

Source: https://habr.com/ru/post/907923/


All Articles