Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to ensure that the WCF ChannelFactory uses Binding settings in xml configuration (MaxArrayLength is ignored)

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.

like image 202
Plastikfan Avatar asked Dec 03 '09 15:12

Plastikfan


1 Answers

I think the problem could be that in config your number only has 6 zeros, while in code you have 7 zeros. Maybe?

like image 189
Klaus Byskov Pedersen Avatar answered Sep 22 '22 14:09

Klaus Byskov Pedersen