【问题标题】:How to fix MaxItemsInObjectGraph error?如何修复 MaxItemsInObjectGraph 错误?
【发布时间】:2011-06-09 19:32:09
【问题描述】:

我有一个 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 代码,您将看到我如何尝试为 DataContractSerializer 行为设置 MaxItemsInObjectGraph 属性。我这样做对吗?

【问题讨论】:

  • 我在某处读到在属性中设置MaxItemsInObjectGraph 不起作用。尝试在配置中设置它 - 它是称为 dataContractSerializer 的服务行为。
  • 好的。这有帮助。但这就是我感到困惑的地方。据我所知,因为我使用的是 SVC 文件和自定义工厂,我的实现将忽略我的配置文件中的任何设置。所以我不知道如何在代码中设置行为。
  • 仅供参考 - 这是我找到我实施的解决方案的地方:stackoverflow.com/questions/4812668/…
  • 在工厂或自定义服务主机的代码中设置行为可能与使用属性具有相同的效果,因为您将在服务描述中搜索行为并更改其配置。我真的不确定我之前的陈述是否正确,但我记得我读到过关于此的一些问题。

标签: wcf rest


【解决方案1】:

我明白了!!!我的客户端代码错误。我正在设置 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();

【讨论】:

  • 是的,可以。大多数设置在频道打开时使用,而不是之后。
  • +1 承认“我通常只是在复制和粘贴代码,而不知道自己在做什么”
【解决方案2】:

您需要使用客户端和服务上的行为在 dataContractSerializer 上设置 MaxItemsInObjectGraph。示例见here

【讨论】:

  • 我不是已经这样做了吗?如果您查看 myService 的代码,您将看到 [ServiceBehavior(MaxItemsInObjectGraph = int.MaxValue) ,如果您查看 myClient 的代码,您将看到与链接中相同的代码。我错过了什么吗?
  • @Corey:不,我在你的代码中错过了这一点。这应该会解决它,我不知道为什么它不会。
  • 谢谢。我做了一些故障排除。似乎序列化在服务器端很好。问题在于客户端的反序列化。但据我所知,我的客户代码是正确的(见上文)。我想知道我做错了什么。
【解决方案3】:

在客户端,实现此目的的另一种方法是创建自定义 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;
        }
    }

【讨论】:

    【解决方案4】:

    您正在返回一个大小超过 65536 的通用列表或数组。在您的查询中,使用 select top 60000 或不添加超过 60k 的元素将解决您的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-04
      • 2016-11-17
      • 2011-07-24
      • 2021-05-10
      • 2017-07-17
      • 2013-03-05
      • 2016-09-10
      • 2020-12-11
      相关资源
      最近更新 更多