четверг, 30 мая 2013 г.

WCF Quotas

When using WCF and transferring rather big objects or collection of objects or objects with a big amount of inner properties through the network, you can encounter a problem something like here:

Failed to invoke the service. Possible causes: The service is offline or inaccessible; the client-side configuration does not match the proxy; the existing proxy is invalid. Refer to the stack trace for more detail. You can try to recover by starting a new proxy, restoring to default configuration, or refreshing the service

The underlying secure session has faulted before the reliable session fully completed. The reliable session was faulted.

Server stack trace:
   at System.Runtime.InputQueue`1.WaitQueueReader.Wait(TimeSpan timeout, T& value)
   at System.Runtime.InputQueue`1.Dequeue(TimeSpan timeout, T& value)
   at System.ServiceModel.Channels.InputQueueChannel`1.Dequeue(TimeSpan timeout, TDisposable& item)
   at System.ServiceModel.Channels.DuplexChannel.TryReceive(TimeSpan timeout, Message& message)
   at System.ServiceModel.Dispatcher.DuplexChannelBinder.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation,
   Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall,
   ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
                                                                         …
When starting WCF service locally – the exception disappears and everything works clearly.
Here are quotas on the level of binding:
MaxBufferPoolSize, MaxBufferSize, MaxReceivedMessageSize, MaxArrayLength, MaxBytesPerRead, MaxDepth, MaxNameTableCharCount, MaxStringContentLength.


Another point is that WCF uses dataContractSerializer or xmlSerializer when transferring objects. DataContractSerializer has maxItemsInObjectGraph property limit. It has 65535 value by default.

Here is possible solution for this problem:

1.      In your server configuration file (App.config/Web.config) find your binding and set required properties that override default values and add dataContractSerializer setting in serviceBehavior section:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.serviceModel>
<behaviors>
      <serviceBehaviors>
        <behavior name="Common">
          <serviceMetadata httpGetEnabled="false"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <dataContractSerializer maxItemsInObjectGraph="2147483646"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
        <bindings>
               <netTcpBinding>
       <binding name="YourBindingName"
                        maxBufferSize="2147483647"
                        MaxBufferPoolSize ="2147483647"
                        maxReceivedMessageSize="2147483647"
                        openTimeout="00:10:00"
                       receiveTimeout="00:10:00"
                       transactionFlow="true" >
          <reliableSession enabled="true" inactivityTimeout="00:10:00"/>
          <readerQuotas maxStringContentLength="2147483647"
                                      maxArrayLength="2147483647"
                                      maxBytesPerRead="2147483647"
                                      maxDepth="2147483647"
                                      MaxNameTableCharCount="2147483647"/>
          <security mode="Transport">
            <transport clientCredentialType="Windows"/>
          </security>
        </binding>
               </netTcpBinding>
        </bindings>
<services>
      <service behaviorConfiguration="Common" name="YourServiceName">
        <host>
          <baseAddresses>
            <add baseAddress="YourServiceBaseAddress" />
          </baseAddresses>
        </host>
        <endpoint name="YourEndpointName" address="" binding="netTcpBinding"
                           bindingConfiguration="YourBindingConfiguration" contract="YourContract" />
        <endpoint address="net.tcp://targetServer:777/Services/YourServiceName/mex"
                            binding="mexTcpBinding"
                            contract="IMetadataExchange" />
      </service>
</services>
        <client>
            <endpoint address="yourAddress"
                binding="netTcpBinding" bindingConfiguration="bindingName"
                contract="yourContract" name="endpointName">
                <identity>
                    <userPrincipalName value="yourUser@yourDomain.com" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>
2.      On the client size open configuration file and set the required options (client needs endpointBehaviors to be set):
<system.serviceModel>
    <behaviors>
    <endpointBehaviors>
        <behavior name="ClientBehavior">
            <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
        </behavior>
    </endpointBehaviors>
    </behaviors>
    <bindings>
      <netTcpBinding>
        <binding name="YourBindingName"
          maxBufferSize="2147483647"
          maxReceivedMessageSize="2147483647"
          openTimeout="00:10:00"
          receiveTimeout="00:10:00"
          transactionFlow="true"
          transactionProtocol="OleTransactions">
          <reliableSession enabled="true" inactivityTimeout="00:10:00"/>
          <readerQuotas
                        maxStringContentLength="2147483647"
                        maxArrayLength="2147483647"
                        maxBytesPerRead="2147483647"
                        maxDepth="2147483647"
                        maxNameTableCharCount="2147483646"
                        />
          <security mode="Transport">
            <transport clientCredentialType="Windows" />
          </security>
        </binding>
      </netTcpBinding>
    </bindings>
    <client>
      <endpoint
        address="YourServiceName"
        binding="netTcpBinding"
        bindingConfiguration=" YourBindingName "
        contract="YourContract"
        name="endpointName"
        behaviorConfiguration="ClientBehavior">
        <identity>
          <userPrincipalName/>
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>

Комментариев нет:

Отправить комментарий