WCF MaxItemsInObjectGraph

 
尝试对参数 http://tempuri.org/ 进行序列化时出错: data。InnerException 消息是“对象图中可以序列化或反序列化的项目数目上限为“65536”。
请更改对象图或增加 MaxItemsInObjectGraph 的配额。 ”。有关详细信息,请参见 InnerException。
 
 
 
 

//序列化最大值

            foreach (var op in client.Endpoint.Contract.Operations)

            {

                var dataContractBehavior = op.Behaviors[typeof(DataContractSerializerOperationBehavior)]

                as DataContractSerializerOperationBehavior;

 

                if (dataContractBehavior != null)

                {

                    dataContractBehavior.MaxItemsInObjectGraph = int.MaxValue;

                }

            }

 

序列化配置

<dataContractSerializer maxItemsInObjectGraph="2147483647" />

 

注意IIS网站传输限制

<httpRuntime

maxRequestLength="20000"

executionTimeout="600"

/>

 

 

 

 

 

 

 

How to set the MaxItemsInObjectGraph configuration.

 

Symptoms/Exceptions:

("System.Runtime.Serialization.SerializationException : Maximum number of items that can be serialized or deserialized in an object graph is '65536'. Change the object graph or increase the MaxItemsInObjectGraph quota.").

"System.ServiceModel.CommunicationException: The underlying connection was closed: The connection was closed unexpectedly"

Solution

You need to modify both the configuration file for the service as well as the client.

For the services configuration should look like this:

<system.serviceModel>    <services>

      <service behaviorConfiguration="Umea.se.EventReactor.ServiceTier.ServiceViewEventBehavior"

       name="Umea.se.EventReactor.ServiceTier.ServiceViewEvent">

        <endpoint address="" binding="wsHttpBinding" contract="Umea.se.EventReactor.ServiceTier.IServiceViewEvent">

          <identity>

            <dns value="localhost" />

          </identity>

        </endpoint>

        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />

      </service>

    </services>

    <behaviors>

      <serviceBehaviors>

        <behavior name="Umea.se.EventReactor.ServiceTier.ServiceViewEventBehavior">

          <serviceMetadata httpGetEnabled="true" />

          <serviceDebug includeExceptionDetailInFaults="false" />

          <dataContractSerializer maxItemsInObjectGraph="2147483647" />

        </behavior>

      </serviceBehaviors>

    </behaviors>

  </system.serviceModel>

 

The client configuration should look like this:

 

<system.serviceModel>

    <client>

<endpoint address="http://localhost:3379/ServiceViewEvent.svc" behaviorConfiguration="ServiceViewEventBehavior"

        binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IServiceViewEvent"

        contract="ServiceReferenceViewEvent.IServiceViewEvent" name="WSHttpBinding_IServiceViewEvent">

        <identity>

          <dns value="localhost" />

        </identity>

      </endpoint>

</client>

<behaviors>

      <endpointBehaviors>

        <behavior name="ServiceViewEventBehavior">

          <dataContractSerializer maxItemsInObjectGraph="2147483647"/>   

        </behavior>

      </endpointBehaviors>

</behaviors>

  </system.serviceModel>

 

 

 

 

 

http://blogs.msdn.com/sowmy/archive/2006/03/26/561188.aspx

 

Preserving Object Reference in WCF

By default object references are not preserved by the DataContractSerializer; Values of an object referenced multiple times is serialized multiple times. If the object is part of mutual (cyclic) reference (e.g. circular linked list) an exception is thrown during serialization.

 

DataContractSerializer can be made to preserve object reference by passing true for parameter PreserveObjectReference when constructing DataContractSerializer as shown below.

 

new DataContractSerializer(type, name, ns, knownTypes,

                0x7FFF /*maxItemsInObjectGraph*/,

                false/*ignoreExtensionDataObject*/,

                true/*preserveObjectReferences*/,

                null/*dataContractSurrogate*/);

 


Enabling in Service Operation

To enable this option in service operation one must pass an instance of DataContractSerializer to the WCF runtime. This can be done by sub classing DataContractSerializerOperationBehavior and overriding CreateSerializer method as shown below.

 

    class ReferencePreservingDataContractSerializerOperationBehavior

      :DataContractSerializerOperationBehavior

    {

        public ReferencePreservingDataContractSerializerOperationBehavior(

          OperationDescription operationDescription)

          : base(operationDescription) { }

        public override XmlObjectSerializer CreateSerializer(

          Type type, string name, string ns, IList<Type> knownTypes)

        {

            return CreateDataContractSerializer(type, name, ns, knownTypes);

        }

 

        private static XmlObjectSerializer CreateDataContractSerializer(

          Type type, string name, string ns, IList<Type> knownTypes)

        {

            return CreateDataContractSerializer(type, name, ns, knownTypes);

        }

 

        public override XmlObjectSerializer CreateSerializer(

          Type type, XmlDictionaryString name, XmlDictionaryString ns,

          IList<Type> knownTypes)

        {

            return new DataContractSerializer(type, name, ns, knownTypes,

                0x7FFF /*maxItemsInObjectGraph*/,

                false/*ignoreExtensionDataObject*/,

                true/*preserveObjectReferences*/,

                null/*dataContractSurrogate*/);

        }

    }

 

The behavior must be added to all the operations on the server side contract. For a self hosted server it can be done as shown below.

 

        ServiceHost host = new ServiceHost(

                             typeof(FooContractImpl), new Uri(address));

        host.AddServiceEndpoint(typeof(FooContract), binding, address);

        foreach (ServiceEndpoint endpoint in host.Description.Endpoints)

            SetDataContractSerializerBehavior(endpoint.Contract);

        host.Open();

 

Similary the behavior must be added to all the operations on the client side as shown below.

 

        ChannelFactory<FooContract> factory = new ChannelFactory<FooContract>(binding, new EndpointAddress(address));

        SetDataContractSerializerBehavior(factory.Endpoint.Contract);

        FooContract proxy = factory.CreateChannel();

 

The SetDataContractSerializerBehavior is defined as shown below.

    private static void SetDataContractSerializerBehavior(ContractDescription contractDescription)

    {

        foreach (OperationDescription operation in contractDescription.Operations)

        {

            operation.Behaviors.Add(new ReferencePreservingDataContractSerializerOperationBehavior(operation));

        }

    }


Enabling via Attribute

This is all good. However wouldn’t it be great if it is possible avoid all the imperative code and instead define an attribute as shown below?

 

[ServiceContract]

public interface FooContract

{

    [OperationContract]

    [ReferencePreservingDataContractFormat]

    Node EchoNode(Node node);

}

 

Yes this can be done by defining a custom attribute that implements IOperationBehavior as shown below.

 

public class ReferencePreservingDataContractFormatAttribute : Attribute, IOperationBehavior

{

    #region IOperationBehavior Members

    public void AddBindingParameters(OperationDescription description, BindingParameterCollection parameters)

    {

    }

 

    public void ApplyClientBehavior(OperationDescription description,System.ServiceModel.Dispatcher.ClientOperation proxy)

    {

        IOperationBehavior innerBehavior = new ReferencePreservingDataContractSerializerOperationBehavior(description);

        innerBehavior.ApplyClientBehavior(description, proxy);

    }

 

    public void ApplyDispatchBehavior(OperationDescription description,System.ServiceModel.Dispatcher.DispatchOperation dispatch)

    {

        IOperationBehavior innerBehavior = new ReferencePreservingDataContractSerializerOperationBehavior(description);

        innerBehavior.ApplyDispatchBehavior(description, dispatch);

    }

 

    public void Validate(OperationDescription description)

    {

    }

 

    #endregion

}

posted @ 2009-04-08 16:52  gameoverboss  阅读(3051)  评论(0编辑  收藏  举报