How to make sure WCF ChannelFactory uses binding settings in xml configuration (MaxArrayLength is ignored)

How to make sure WCF ChannelFactory uses binding settings in xml configuration (MaxArrayLength is ignored)

Hi, I am new to Wcf and am writing my first Wcf service and client. I prefer not to use configuration tools; I would rather write the configuration myself. The problem I'm trying to solve is the client interacting with the service through netTcp. The service can potentially return very large payloads (better than the default readerQuotas.maxArrayLength). Initially, the components I developed work fine when byte data streams are relatively low (i.e., less than the default, which in his opinion is around 16K). I can solve this problem programmatically by creating a binding and setting MaxArrayLength to a sufficiently large value. However, I need to be able to execute the equivalent in xml.

My app.config (client):

<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <client> <endpoint address="net.tcp://localhost:9000/WcfDataService/RemoteDataRequesterService/" binding="netTcpBinding" bindingConfiguration="unsecureNetTcpBinding" contract="WcfDataServiceLib.IRemoteDataRequester" name="DataRequesterEndpoint" /> </client> <bindings> <netTcpBinding> <binding name="unsecureNetTcpBinding" maxReceivedMessageSize="2147483647"> <readerQuotas maxArrayLength="1000000" /> <security mode="None" /> </binding> </netTcpBinding> </bindings> </system.serviceModel> </configuration> 

The code for creating the client proxy is as follows:

 private void Init() { var address = new EndpointAddress(@"net.tcp://localhost:9000/WcfDataService/RemoteDataRequesterService/"); const string endpointName = "DataRequesterEndpoint"; ChannelFactory<IRemoteDataRequester> factory = new ChannelFactory<IRemoteDataRequester>( endpointName); IRemoteDataRequester proxy = factory.CreateChannel(address); // call business methods on proxy ... } 

Note that the code is related to the configuration of the variable 'endpointName'.

Service side configuration (I do not think this is relevant, but included for completeness):

 <?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <services> <service name="WcfDataServiceLib.RemoteDataRequesterService" behaviorConfiguration="WcfDataServiceLib.RemoteDataRequesterServiceBehavior"> <host> <baseAddresses> <add baseAddress = "net.tcp://localhost:9000/WcfDataService/RemoteDataRequesterService" /> <add baseAddress="http://localhost:8731/Design_Time_Addresses/WcfDataService/RemoteDataRequesterService/"/> </baseAddresses> </host> <endpoint address ="" binding="netTcpBinding" bindingConfiguration="netTcpBindingConfig" contract="WcfDataServiceLib.IRemoteDataRequester"> <identity> <dns value="localhost"/> </identity> </endpoint> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> </service> </services> <behaviors> <serviceBehaviors> <behavior name="WcfDataServiceLib.RemoteDataRequesterServiceBehavior"> <serviceMetadata httpGetEnabled="False"/> <serviceDebug includeExceptionDetailInFaults="True" /> </behavior> </serviceBehaviors> </behaviors> <bindings> <netTcpBinding> <binding name="netTcpBindingConfig" receiveTimeout="00:00:30"> <readerQuotas maxArrayLength="1000000"/> </binding> <binding name="netTcpReliableSession" receiveTimeout="00:00:30" > <reliableSession enabled="true"/> </binding> </netTcpBinding> </bindings> </system.serviceModel> </configuration> 

When I run the client in a scenario in which a large stream of bytes is returned by the service, an exception is thrown, and the message inside the exception:

Communication error: The socket connection was interrupted. This can be caused by mistake while processing your message or receiving timeout exceeded by the remote host, or the main network resource. The local socket timeout was "00: 00: 59.9687494"

(This is not a wait time, because the error occurs immediately.)

As stated earlier, I can fix this programmatically as follows:

 var binding = new NetTcpBinding { ReaderQuotas = { MaxArrayLength = 10000000 } }; return new ChannelFactory<IRemoteDataRequester>(binding); 

this works fine, but I need to do this through the config for testing purposes.

I also tried the following:

 var binding = new NetTcpBinding("unsecureNetTcpBinding"); return new ChannelFactory<IRemoteDataRequester>(binding); 

But it does not matter.

So my question is why, when I create a channel from an endpoint configuration that includes a binding with MaxArrayLength set to a suitable value, is this value ignored?

Sincerely.

Ok, I found a solution. The configuration worked all the time. However, the configuration I provided ("unsecureNetTcpBinding"), which I found from the sample code illustrating the http services (and not the net tcp service that I am developing). Fraud 'security mode = "No"' When I realized this, it worked. If I change readerQuotas maxArrayLength, this applies as needed. The reason my code worked was because I did not set the security mode to none. Thanks for your comments and help.

+6
config wcf wcf-binding wcf-client
source share
2 answers

I think the problem may be that in the configuration, your number has only 6 zeros, and in the code you have 7 zeros. May be?

+1
source share

Perhaps MaxArrayLength is not a suitable property.

Try "maxBufferSize" and "MaxBufferPoolSize":

 <bindings> <netTcpBinding> <binding name="unsecureNetTcpBinding" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"> <readerQuotas maxArrayLength="1000000" /> <security mode="None" /> </binding> </netTcpBinding> </bindings> 

But the real question is: if you have a lot of data, why not use WCF streaming ? This is exactly what it is intended for.

http://www.haveyougotwoods.com/archive/2008/04/14/wcf-message-streaming.aspx

Dimensions maxBufferSize, etc. are installed with a fairly small value to avoid denial of service attacks. Simply rolling up the levels to MaxInt makes your server vulnerable to these DOS attacks.

UPDATE:
Try this: - create a new console application - add links to System.Runtime.Serialization and System.ServiceModel - add app.config, which contains exactly what your client side config contains. - put these lines of code in a console application:

  class Program { static void Main(string[] args) { NetTcpBinding binding = new NetTcpBinding("unsecureNetTcpBinding"); int maxArrayLength = binding.ReaderQuotas.MaxArrayLength; long maxReceivedMessageSize = binding.MaxReceivedMessageSize; } } 
  • run and debug - what values ​​do you get? I get exactly what you entered: "1,000,000" for binding.ReaderQuotas.MaxArrayLength , "2147483647" for binding.MaxReceivedMessageSize.

WCF recognizes and uses these settings from config - 120% guaranteed. Your app should have something else fishy.

0
source share

All Articles