Как исправить ошибку MaxItemsInObjectGraph? - PullRequest
11 голосов
/ 09 июня 2011

У меня есть служба RESTful WCF, и я получаю следующую ошибку: Максимальное количество элементов, которые можно сериализовать или десериализовать в графе объектов, равно «65536».Измените граф объекта или увеличьте квоту MaxItemsInObjectGraph.

Я думал, что решил это, но, видимо, нет.Вот мой код:

Я использую файл .SVC, который использует пользовательскую фабрику, подобную этой:

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

Вот код для пользовательской фабрики

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);
    }
}

Служба:

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

Клиент:

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
}

ОБНОВЛЕНИЕ: Я сделал небольшое устранение неполадок.Кажется, что часть сериализации работает нормально на сервере.Я могу сделать GET из браузера и получаю обратно все данные в формате XML.Так что это работает нормально.Кажется, это часть десериализации, которая вызывает ошибку.Если вы посмотрите выше в коде для myClient, вы увидите, как я пытаюсь установить свойство MaxItemsInObjectGraph для поведения DataContractSerializer.Я делаю это правильно?

Ответы [ 4 ]

23 голосов
/ 10 июня 2011

Я понял это !!!Мой код клиента был неверным.Я устанавливал MaxItemsInObjectGraph после Я уже создал свой канал.Таким образом, свойство MaxItemInObjectGraph не влияло на уже созданный канал.(Этот материал WCF меня так смущает - я обычно просто копирую и вставляю код, не зная, что я делаю) Вот исправленный код:

        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();
4 голосов
/ 09 июня 2011

Вам необходимо установить MaxItemsInObjectGraph для dataContractSerializer, используя поведение как клиента, так и службы.См. здесь для примера.

0 голосов
/ 30 января 2013

В ваших запросах вы возвращаете общий список или массив, размер которого превышает 65536. Использование топ-600 600 или отсутствие добавления более 60 тыс. Элементов решит вашу проблему.

0 голосов
/ 23 января 2013

На стороне клиента еще один способ добиться этого - создать собственную реализацию IEndPointBehavior - см. http://canbilgin.wordpress.com/2010/06/25/how-to-set-maxitemsinobjectgraph-programmatically-for-client/.

Это особенно полезно при реализации клиента с 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;
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...