При отправке байта [] HttpClient в службу WCF возникает ошибка: максимальная квота длины массива (16384) или максимальное количество элементов

У меня есть служба WCF, которая может принимать byte[]. Я создаю клиента с помощью HttpClient и получаю следующую ошибку. Я читал в Интернете, что вы должны установить readerQuotas как на сервере, так и на клиенте, но как мне установить эти настройки на HttpClient?

Ошибка:

Произошла ошибка десериализации объекта типа RTM.API.Resources.UGCRequest. Квота максимальной длины массива (16384) или максимальное количество элементов в квоте графа объектов превышены при чтении данных XML. Эти квоты можно увеличить, изменив свойство MaxArrayLength в XmlDictionaryReaderQuotas или параметр MaxItemsInObjectGraph.

Конфигурация сервера:

    <standardEndpoints>
        <webHttpEndpoint>
            <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647" maxBufferSize="2147483647"/>
            <standardEndpoint name="DirectoryEndpoint"/>
        </webHttpEndpoint>
    </standardEndpoints>
    <services>
        <service name="API.Service.UGCService" behaviorConfiguration="DataServiceBehavior">
            <endpoint contract="API.Service.UGCService" kind="webHttpEndpoint" endpointConfiguration="" binding="webHttpBinding" bindingConfiguration="BigHttpBinding"/>
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="DataServiceBehavior">
                <serviceDebug includeExceptionDetailInFaults="true"/>
                <dataContractSerializer maxItemsInObjectGraph="2147483644"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <bindings>
        <webHttpBinding>
            <binding name="BigHttpBinding" transferMode="Buffered" maxReceivedMessageSize="2147483647" >
                <readerQuotas maxArrayLength="2147483647" maxDepth="2147483647" maxStringContentLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
            </binding>
        </webHttpBinding>
    </bindings>

Код клиента:

using (HttpClient client = new HttpClient(apiPath))
            {
                using (HttpRequestMessage request = new HttpRequestMessage(method, finalUrl))
                {
                    request.Headers.Accept.AddString("application/json");
                    request.Headers.Add("Authorization", sb.ToString());

                    if (method == "POST" || method == "PUT")
                    {
                        if (requestBody.Count() == 0)
                            request.Headers.ContentLength = 0;
                        else
                        {
                            request.Content = HttpContent.Create(APM6.Utils.Serialize(requestBody), "application/json");
                        }
                    }

                    using (HttpResponseMessage response = client.Send(request))
                    {
                        return response.Content.ReadAsString();
                    }
                }
            }

person Troy Barlow    schedule 19.06.2012    source источник
comment
Не по теме, я борюсь с WCF в течение 6 месяцев, и я бы не рекомендовал использовать его для раскрытия интерфейса JSON (его множество сложностей не окупает усилий). Если вы хотите придерживаться технологий Microsoft и можете оценить альтернативу, взгляните на WebAPI.   -  person Gerardo Lima    schedule 28.06.2012


Ответы (3)


readerQuotas - это набор дополнительных ограничений, которые WCF реализует для защиты от атак типа «отказ в обслуживании» (DOS).

HttpClient не реализует эту защиту, поэтому вам не нужно беспокоиться о дополнительной настройке клиента.

Вы видите эту ошибку, потому что <readerQuotas maxArrayLength="2147483647" /> по какой-то причине не применяется к конечной точке вашего сервера. Вы можете использовать svcutil.exe или wcftestclient.exe, чтобы доказать это.

Попробуйте создать файл конфигурации с помощью этих инструментов, и вы, вероятно, увидите <readerQuotas maxArrayLength="16384" /> в этом файле конфигурации. Это означает, что серверная часть не применила расширенное значение к maxArrayLength.

Если это правда, поиграйте с конфигурацией или кодом на стороне сервера, чтобы убедиться, что конфигурация применена.

person Dmitry Harnitski    schedule 25.06.2012

Попробуй это:

  <endpointBehaviors>
    <behavior name ="namespace1.namespace1Behavior">
      <dataContractSerializer maxItemsInObjectGraph ="2147483647"/>
    </behavior>
    <behavior name="mybehavior">
      <transactedBatching maxBatchSize="2147483647"/>
    </behavior>
  </endpointBehaviors>

  <serviceBehaviors>
    <behavior name="namespace1.namespace1Behavior">
      <dataContractSerializer maxItemsInObjectGraph ="2147483647"/>
      <!-- To avoid disclosing metadata information, 
      set the value below to false and remove the metadata endpoint above before deployment -->
      <serviceMetadata httpGetEnabled="True"/>
      <!-- To receive exception details in faults for debugging purposes, 
      set the value below to true.  Set to false before deployment 
      to avoid disclosing exception information -->
      <serviceDebug includeExceptionDetailInFaults="True" />
    </behavior>
  </serviceBehaviors>
</behaviors>
person Sabri Ghaith    schedule 25.06.2012

В этом случае единственная настройка, которая вам нужна на клиенте, - MaxResponseContentBufferSize.

Однако ваша проблема возникла во время десериализации на сервере. Возможно, вам потребуется добавить maxBufferPoolSize="2147483647" maxBufferSize="2147483647" в качестве параметров привязки

Это все еще не совсем соответствует сообщению об ошибке. Убедитесь, что поведение службы соответствует файлу конфигурации, указанному в вопросе, а не какой-либо другой копии.

person Jirka Hanika    schedule 20.06.2012
comment
Я добавил maxBufferPoolSize = 2147483647 maxBufferSize = 2147483647 в привязку и все еще получаю сообщение об ошибке. Ошибка действительно происходит на сервере? Есть другие идеи? - person Troy Barlow; 22.06.2012
comment
@TroyBarlow - Да, на сервере происходит десериализация запроса. Я думаю, что вы программно дублируете некоторые из опубликованных конфигураций сервера или используете ServiceBehaviorAttribute в коде на стороне сервера (получая значение по умолчанию MaxItemsInObjectGraph из 65536). Обратите внимание, что при сериализации или десериализации массивов каждая запись массива считается отдельным объектом. В этом случае также установите MaxItemsInObjectGraph в атрибуте. - person Jirka Hanika; 29.06.2012