HttpClient将byte[]发布到WCF服务会产生错误:最大数组长度配额(16384)或最大项数已被超出。

3
我有一个可以接受byte[]的WCF服务。我正在使用HttpClient创建客户端,并收到以下错误。我在网上阅读到,你必须在服务器和客户端都设置readerQuotas,但是我该如何在HttpClient上设置这些设置呢?

错误:

反序列化RTM.API.Resources.UGCRequest类型对象时发生错误。读取XML数据时已超过最大数组长度配额(16384)或对象图中的最大项数配额。可以通过更改XmlDictionaryReaderQuotas上的MaxArrayLength属性或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();
                    }
                }
            }

仅作为离题的一句话,我已经苦苦挣扎了6个月的WCF,我不建议使用它来暴露JSON接口(它的许多复杂性并不值得这样做)。如果你想坚持使用微软技术并且可以评估替代方案,请看看WebAPI。 - Gerardo Lima
3个回答

3
readerQuotas是WCF实现的一组附加限制,以提供保护免受拒绝服务攻击(DOS)。 HttpClient没有实现该保护,因此您无需担心额外的客户端配置。
您看到该错误是因为某种原因未将<readerQuotas maxArrayLength="2147483647" />应用于您的服务器端点。您可以使用svcutil.exewcftestclient.exe证明这一点。
尝试使用这些工具生成配置文件,您可能会在该配置文件中看到<readerQuotas maxArrayLength="16384" />。这意味着服务器部分未将扩展值应用于maxArrayLength
如果是这样,可以尝试调整服务器端的配置或代码,以确保已应用配置。

2
请尝试以下方法:

  <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>

1
在这种情况下,客户端唯一需要的设置是MaxResponseContentBufferSize
然而,您的问题发生在服务器上的反序列化过程中。您可能需要将maxBufferPoolSize="2147483647" maxBufferSize="2147483647"添加为绑定参数。
这仍然似乎不完全对应于错误消息。请确保服务行为与问题中显示的配置文件相对应,而不是其他副本。

我在绑定中添加了maxBufferPoolSize="2147483647" maxBufferSize="2147483647",但仍然出现错误。这个错误一定是发生在服务器上吗?还有其他的想法吗? - Troy Barlow
@TroyBarlow - 是的,请求反序列化是在服务器上发生的。我认为你在服务器端代码中以编程方式遮掩了一些已发布的服务器配置或使用了 ServiceBehaviorAttribute(获取默认的 MaxItemsInObjectGraph值为65536)。请注意,在序列化或反序列化数组时,每个数组条目都计算为单独的对象。如果是这种情况,请在属性中设置 MaxItemsInObjectGraph 值。 - Jirka Hanika

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接