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);
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.