How to ensure that the WCF ChannelFactory uses Binding settings in xml configuration (MaxArrayLength is ignored)
Hi, I am new to Wcf and and writing my first Wcf service and client. I prefer not to use tools to generate config; I would rather write the config myself. The problem I am trying to solve is of a client communicating with a service over netTcp. The service can potentially return very large payloads (greather than the default readerQuotas.maxArrayLength). The components I have initially developed work fine when the byte stream payloads are relatively low (ie less than the default which it think is about 16K). I can solve this problem programmicatically by creating a binding and setting MaxArrayLength to a sufficiently large value. However, I need to be able to perform the equivalent in the xml configuration.
My app.config (client) is:
<?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 to create 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 linked to the config by the variable 'endpointName'.
Service side config (I don't 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 byte stream is returned by the service, an exception is thrown and the message inside the exception is:
Communication Error occured: The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:00:59.9687494'
(This is not a timeout as the error occurs immediately.)
As previously stated, I can fix this programmatically as follows:
var binding = new NetTcpBinding
{
ReaderQuotas = { MaxArrayLength = 10000000 }
};
return new ChannelFactory<IRemoteDataRequester>(binding);
this works ok, but I need to do it via config for testing purposes.
I have also tried the following:
var binding = new NetTcpBinding("unsecureNetTcpBinding");
return new ChannelFactory<IRemoteDataRequester>(binding);
But this makes no difference.
So my question is why, when I create the channel from the endpoint config which includes a binding with MaxArrayLength set to a suitable value, is this value ignored?
Many regards.
Ok, I have found the solution. The configuration was working all along. However, the config that I provided ("unsecureNetTcpBinding") which I found from a code sample illustrating http services (not net tcp service which is what I'm designing). The rogue piece of config was 'security mode="None"' When I took this out, it worked. If I change readerQuotas maxArrayLength this is applied as I require. The reason why my code worked is because I was not setting the security mode to none. Thanks for your comments and assistance.