Encountering max message size quota in WCF

158 views Asked by At

I have inherited a WCF component where the service is a SQL query-like service. It takes in a query and in turn passes the query on to another web service. The problem is that by default, the WCF web service client accepts 100 results only. While it is able to remove this limit, once removed it encounters the max message size for incoming messages (65536) error. A brief architecture is as below. The client will consume a WCF service which in turn makes another service call.

Brief architecture

This is the WCF Web.config

<system.serviceModel>
    <diagnostics performanceCounters="Default">
        <messageLogging logEntireMessage="true" />
    </diagnostics>
    <bindings>
        <basicHttpBinding>
            <binding name="basicBinding" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
                <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="36384" />
            </binding>
        </basicHttpBinding>
        <webHttpBinding>
            <binding maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" />
        </webHttpBinding>
    </bindings>
    <services>
        <service name="MYWCF.DfsWcf">
            <clear />
            <endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicBinding" contract="MYWCF.IDfsWcf">
                <identity>
                    <dns value="localhost" />
                </identity>
            </endpoint>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
            <host>
                <baseAddresses>
                    <add baseAddress="http://mercury/MOM_WCF/" />
                </baseAddresses>
            </host>
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="">
                <serviceMetadata httpGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="false" />
            </behavior>
        </serviceBehaviors>
    </behaviors>
</system.serviceModel>

I have tried to set the maxReceivedMessageSize in the wcfTestClient config. I have also written a standalone web service client. Both returns the same 64k max message error.

I have tested not making the chained web service call and instead looping and returning some dummy data, and it is able to return the desired number of results I need (this web service is a SQL query-like service, where it takes in a query and returns the String results to the client). Thus, it seems like the problem exists when the WCF acts as the web service client to the DFS (Documentum Foundation Services) web service, and that the response message returned exceeded the 64k limit. How do I set the maxReceivedMessageSize for the web service client in WCF?

Edit: added the WCF code and the code it uses to call DFS.

    public List<String[]> DoQuery(String username, String password, String repository, String query)
    {
        log4net.Config.XmlConfigurator.Configure();
        log.Debug("DoQuery started..");
        List<String[]> results = new List<String[]>();
        try
        {
            var prop = new Properties();
            var dfs = new DFSCore();
            var serviceContext = dfs.GetServiceContext(repository, username, password, prop.Domain);
            var queryService = dfs.GetQueryService(serviceContext, prop.Address);
            log.Debug("Executing DQL: " + query);

            /*
            for (int i = 0; i < 3000; i++)
            {
                results.Add(new string[] { "" + i, "objectID=" + i });
            }
            */

            //return results;
            return dfs.ExecuteDql(queryService, query, prop.DocBase, int.Parse(prop.MaxResultCount));
        }
        catch (Exception e)
        {
            log.Error(e);
            throw e;
        }
    }

   public List<String[]> ExecuteDql(IQueryService querySvc, String dqlQuery, String repositoryName, int maxResultCount)
    {
        log4net.Config.XmlConfigurator.Configure();
        var results = new List<String[]>();

        try
        {
            var query = new PassthroughQuery { QueryString = dqlQuery };
            query.AddRepository(repositoryName);
            var queryEx = new QueryExecution { CacheStrategyType = CacheStrategyType.DEFAULT_CACHE_STRATEGY };
            queryEx.MaxResultCount = maxResultCount;
            queryEx.MaxResultPerSource = maxResultCount;

            List<String> fieldNames = new List<String>();
            String[] temp = dqlQuery.Split(new String[] { "from" }, StringSplitOptions.None);

            if (temp[0].StartsWith("select "))
            {
                string fields = temp[0].Substring("select ".Length).Trim();
                DFSCore.log.Debug("fields = " + fields);
                string[] temp2 = fields.Split(new char[] { ',' });
                foreach (string field in temp2)
                {
                    DFSCore.log.Debug("\tfield = " + field);
                    string[] temp3 = field.Split(new string[] { " as " }, StringSplitOptions.None);
                    DFSCore.log.Debug(string.Concat(new object[] { "\t\ttemp3 = ", temp3, ", length = ", temp3.Length }));
                    if (temp3.Length == 1)
                    {
                        if (temp3[0].Contains("."))
                        {
                            temp3[0] = temp3[0].Split(new string[] { "." }, StringSplitOptions.None)[1];
                        }
                        DFSCore.log.Debug("\t\t\tadding fieldName " + temp3[0].Trim());
                        fieldNames.Add(temp3[0].Trim());
                    }
                    else
                    {
                        DFSCore.log.Debug("\t\t\tadding fieldName " + temp3[1].Trim());
                        fieldNames.Add(temp3[1].Trim());
                    }
                }
            }

            var queryResult = querySvc.Execute(query, queryEx, null);
            var dataPackage = queryResult.DataPackage;
            var dataObjects = dataPackage.DataObjects;

            int index = 0;
            //convert the results into a List<AclIdentity>
            foreach (var dObj in dataObjects)
            {
                var docProperties = dObj.Properties;
                String[] temp4 = new String[fieldNames.Count];

                for (int i = 0; i < fieldNames.Count; i++)
                {
                    String fieldName = fieldNames[i];
                    var result = docProperties.Get(fieldName).GetValueAsString();
                    temp4[i] = result;
                    DFSCore.log.Debug(string.Concat(new object[] { "[", index, "] fieldName[" + i + "] = ", fieldName, ", value = ", result }));
                }
                results.Add(temp4);
                index++;
            }
        }
        catch (Exception e)
        {
            DFSCore.log.Error(e);
        }
        return results;
    }
}
1

There are 1 answers

0
Ding Peng On

You also need to set the value of MaxReceivedMessageSize in the client configuration file.

Setting the client's MaxReceivedMessageSize will affect the length of the message received by the client, and it has no effect on the message received by the service. Your configuration file only configures the MaxReceivedMessageSize on the server side.

Client configuration file:

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="basicBinding" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"/>
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://localhost:8733/Service1/"
            binding="basicHttpBinding" bindingConfiguration="basicBinding"
            contract="ServiceReference1.IService1" name="BasicHttpBinding_IService1" />
    </client>
</system.serviceModel>

Feel free to let me know if the problem persists.