Monday, September 13, 2010

Sneaky MaxItemsInObjectGraph attribute in WCF

I spent almost couple of days trying to figure out what caused WCF service to crash (in a weird way) when it was tried to return large resultset.
Initially the problem expressed itself on the WCF client side. When number of records in returning results was close to 5000 – WCF client generated
Meaningless "An existing connection was forcibly closed by the remote host." exception.
Google search for '"An existing connection was forcibly closed by the remote host." WCF size' brought up
WCF issues sending large data forum discussion.
The right answer (maxItemsInObjectGraph) was mentioned there, but it was buried under pile of misleading suggestions.

One step toward the solution was to use soapUI utility to make the requests (instead of calling WCF service from another .NET client).
That helped to determine that the problem is on the WCF server side -- soapUI simply couldn't get any response (when number of returning dataset rows was ~5000+).

What really helped to find the final answer -– was enabling WCF diagnostic by adding this to web.config on server side:
<system.diagnostics>
<sources>
<source name="System.ServiceModel" switchValue="Warning, ActivityTracing"
propagateActivity="true">
<listeners>
<add type="System.Diagnostics.DefaultTraceListener" name="Default">
<filter type="" />
</add>
<add name="ServiceModelTraceListener">
<filter type="" />
</add>
</listeners>
</source>
</sources>
<sharedListeners>
<add initializeData="app_tracelog.svclog"
type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089"
name="ServiceModelTraceListener" traceOutputOptions="Timestamp">
<filter type="" />
</add>
</sharedListeners>
</system.diagnostics>
Then app_tracelog.svclog revealed much more specific error message:
---
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. '
---
Quick googling for "maxItemsInObjectGraph" brought me to MaxItemsInObjectGraph and keeping references when serializing in WCF blog post which recommended to add the following section to WCF server web.config:
<behaviors>
<serviceBehaviors>
<behavior name="LargeServiceBehavior">
<dataContractSerializer maxItemsInObjectGraph="100000"/>
</behavior>
</serviceBehaviors>
</behaviors>
and this section to WCF client web.config:
<behaviors>
<endpointBehaviors>
<behavior name="LargeEndpointBehavior">
<dataContractSerializer maxItemsInObjectGraph="100000"/>
</behavior>
</endpointBehaviors>
</behaviors>
That worked.
I used VS.NET 2008 / .NET Framework 3.5, but I think that is applicable to .NET 4.0 too.

Enjoy.

No comments:

Followers

About Me

My photo
Email me: blog@postjobfree.com