“The maximum string content length quota (8192) has been exceeded while reading XML data” error while sending XML string to WCF

StackOverflow https://stackoverflow.com/questions/19543554

  •  01-07-2022
  •  | 
  •  

Question

I have trying everything in three days to fix this error in my application in client and server config, but nothing helps, this is my configs:

Client:

public class IdBookIssuerIssuedTokenBinding : WS2007HttpBinding
{
    private readonly HttpTransportBindingElement transport;
    private readonly SecurityBindingElement security;

    public IdBookIssuerIssuedTokenBinding(EndpointAddress bindingAddress)
    {
        WS2007HttpBinding ws2007HttpBinding = new WS2007HttpBinding(SecurityMode.TransportWithMessageCredential);
        ws2007HttpBinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
        ws2007HttpBinding.Security.Message.EstablishSecurityContext = false;

        //TODO: expose somewhere to configure this timeouts
        ws2007HttpBinding.SendTimeout = TimeSpan.FromMinutes(5);
        ws2007HttpBinding.ReceiveTimeout = TimeSpan.FromMinutes(5);

        ws2007HttpBinding.MaxReceivedMessageSize = int.MaxValue;
        ws2007HttpBinding.MaxBufferPoolSize = int.MaxValue;
        ws2007HttpBinding.ReaderQuotas.MaxStringContentLength = int.MaxValue;
        ws2007HttpBinding.ReaderQuotas.MaxNameTableCharCount = int.MaxValue;
        ws2007HttpBinding.ReaderQuotas.MaxDepth = int.MaxValue;
        ws2007HttpBinding.ReaderQuotas.MaxBytesPerRead = int.MaxValue;
        ws2007HttpBinding.ReaderQuotas.MaxArrayLength = int.MaxValue;

        this.ReaderQuotas.MaxStringContentLength = int.MaxValue;
        this.ReaderQuotas.MaxNameTableCharCount = int.MaxValue;
        this.ReaderQuotas.MaxDepth = int.MaxValue;
        this.ReaderQuotas.MaxBytesPerRead = int.MaxValue;
        this.ReaderQuotas.MaxArrayLength = int.MaxValue;

        IssuedSecurityTokenParameters securityTokenParameters = new System.ServiceModel.Security.Tokens.IssuedSecurityTokenParameters(
            "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1",
                bindingAddress,
                ws2007HttpBinding);

        security = SecurityBindingElement.CreateIssuedTokenOverTransportBindingElement(securityTokenParameters);
        security.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10;

        transport = new HttpsTransportBindingElement();
        transport.MaxReceivedMessageSize = int.MaxValue;
        transport.MaxBufferSize = int.MaxValue;
        transport.MaxBufferPoolSize = int.MaxValue;

        this.MessageEncoding = WSMessageEncoding.Text;
        this.MaxBufferPoolSize = int.MaxValue;
        this.MaxReceivedMessageSize = int.MaxValue;
    }

    public override BindingElementCollection CreateBindingElements()
    {
        BindingElementCollection elements = new BindingElementCollection();

        elements.Add(this.security);
        elements.Add(this.transport);

        return elements;
    }
}

public class ClientFactory
{
    #region static

    private readonly static ClientFactory _current;

    static ClientFactory()
    {
        _current = new ClientFactory();
    }

    public static ClientFactory Current { get { return _current; } }

    #endregion

    private ClientFactory()
    { }

    public TClient Create<TClient, TServiceInterface>(string businessEntityContainerName, string userName, string password) 
            where TClient : ClientBase<TServiceInterface>, new()
            where TServiceInterface : class
    {
        var client = new TClient();
        return this.Create<TClient, TServiceInterface>(client, businessEntityContainerName, userName, password);
    }

    public TClient Create<TClient, TServiceInterface>(string businessEntityContainerName, string userName, string password, Binding stsBinding, EndpointAddress remoteServiceAddress)
            where TClient : ClientBase<TServiceInterface>, new()
            where TServiceInterface : class
    {
        var client = (TClient)Activator.CreateInstance(typeof(TClient), stsBinding, remoteServiceAddress);
        return this.Create<TClient, TServiceInterface>(client, businessEntityContainerName, userName, password);
    }

    public TClient Create<TClient, TServiceInterface>(string businessEntityContainerName, string userName, string password, EndpointAddress stsAddress, EndpointAddress remoteServiceAddress)
            where TClient : ClientBase<TServiceInterface>, new()
            where TServiceInterface : class
    {
        IdBookIssuerIssuedTokenBinding binding = new IdBookIssuerIssuedTokenBinding(stsAddress);

        var client = (TClient)Activator.CreateInstance(typeof(TClient), binding, remoteServiceAddress);
        return this.Create<TClient, TServiceInterface>(client, businessEntityContainerName, userName, password);
    }

    private TClient Create<TClient, TServiceInterface>(TClient client, string businessEntityContainerName, string userName, string password)
            where TClient : ClientBase<TServiceInterface>, new()
            where TServiceInterface : class
    {
        client.ClientCredentials.UserName.UserName = userName;
        client.ClientCredentials.UserName.Password = password;

        //TODO: expose somewhere to configure this timeouts
        var binding = (IdBookIssuerIssuedTokenBinding)client.Endpoint.Binding;
        binding.SendTimeout = TimeSpan.FromMinutes(2);
        binding.ReceiveTimeout = TimeSpan.FromMinutes(5);

        binding.ReaderQuotas.MaxStringContentLength = int.MaxValue;
        binding.ReaderQuotas.MaxNameTableCharCount = int.MaxValue;
        binding.ReaderQuotas.MaxDepth = int.MaxValue;
        binding.ReaderQuotas.MaxBytesPerRead = int.MaxValue;
        binding.ReaderQuotas.MaxArrayLength = int.MaxValue;

        client.Endpoint.Behaviors.Add(new HeaderInfoBehavior(businessEntityContainerName));

        foreach (var operation in client.ChannelFactory.Endpoint.Contract.Operations)
        {
            var dtSerializerOp = operation.Behaviors.Find<DataContractSerializerOperationBehavior>();

            dtSerializerOp.DataContractResolver =
                    new DynamicTypeResolver(typeof(TClient).Assembly, typeof(TClient).Namespace);

            dtSerializerOp.MaxItemsInObjectGraph = int.MaxValue;
        }

        return client;
    }
}

Service:

<?xml version="1.0"?>
<configuration>
  <location path="Services">
    <system.web>
      <authorization>
        <allow users="*" />
      </authorization>
      <httpRuntime executionTimeout="4800" maxRequestLength="2097150"/>
    </system.web>
  </location>
  <system.serviceModel>
    <extensions>
      <behaviorExtensions>
        <add name="errorHandler" type="GILabs.MetaFx.Application.Service.Commom.ErrorHandlerBehavior, GILabs.MetaFx.Application.Service.Commom" />
        <add name="federatedServiceHostConfiguration" type="Microsoft.IdentityModel.Configuration.ConfigureServiceHostBehaviorExtensionElement, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
      </behaviorExtensions>
    </extensions>
    <behaviors>
      <serviceBehaviors>
        <behavior name="WsServiceBehavior">
          <dataContractSerializer maxItemsInObjectGraph="2147483647" />
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
          <errorHandler />
          <federatedServiceHostConfiguration />
        </behavior>
      </serviceBehaviors>

      <endpointBehaviors>
        <behavior name="WsServiceBehavior">
          <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <bindings>
      <wsHttpBinding>
        <binding name="WsHttpEndpointBinding">
        </binding>
      </wsHttpBinding>
      <ws2007FederationHttpBinding>
        <binding name="IDBookIssuerIssuedTokenFederation" closeTimeout="00:10:00" openTimeout="00:10:00"
          receiveTimeout="00:10:00" sendTimeout="00:10:00" bypassProxyOnLocal="false"
          transactionFlow="false" hostNameComparisonMode="StrongWildcard"
          maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text"
          textEncoding="utf-8" useDefaultWebProxy="true">
          <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647"
            maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />

          <security mode="TransportWithMessageCredential">
            <message establishSecurityContext="false">
              <issuer address="https://localhost/idbook/Services/SecurityToken.svc" binding="customBinding" bindingConfiguration="IDBookIssuerIssuedToken" />
            </message>
          </security>
        </binding>
      </ws2007FederationHttpBinding>
      <ws2007HttpBinding>
        <binding name="IDBookIssuerUsernameMixed">
          <security mode="TransportWithMessageCredential">
            <message clientCredentialType="UserName" establishSecurityContext="false" />
          </security>
        </binding>
      </ws2007HttpBinding>
      <customBinding>
        <binding name="IDBookIssuerIssuedToken">
          <security authenticationMode="IssuedTokenOverTransport"
                    messageSecurityVersion="WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10">
            <issuedTokenParameters>
              <issuer address="https://localhost/idbook/Services/SecurityToken.svc"
                      binding="ws2007HttpBinding" bindingConfiguration="IDBookIssuerUsernameMixed">
              </issuer>
            </issuedTokenParameters>
          </security>
          <textMessageEncoding maxReadPoolSize="2147483647" maxWritePoolSize="2147483647">
            <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
              maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
          </textMessageEncoding>
          <httpTransport maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
            maxBufferSize="2147483647" />
        </binding>
      </customBinding>
    </bindings>
    <services>
      <service behaviorConfiguration="WsServiceBehavior" name="GILabs.MetaFx.Application.MetadataService.MetaService">
        <endpoint address="" binding="ws2007FederationHttpBinding"
          bindingConfiguration="IDBookIssuerIssuedTokenFederation"
          name="MetadataWsHttpEndpoint" contract="GILabs.MetaFx.Application.MetadataService.IMetadataService">
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
      <service behaviorConfiguration="WsServiceBehavior" name="GILabs.MetaFx.Application.Service.AppService">
        <endpoint address="" binding="ws2007FederationHttpBinding"
          bindingConfiguration="IDBookIssuerIssuedTokenFederation"
          name="ApplicationWsHttpEndpoint" contract="GILabs.MetaFx.Application.Service.IAppService">
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
      <service behaviorConfiguration="WsServiceBehavior" name="GILabs.MetaFx.Application.Service.SyncChangeService">
        <endpoint address="" binding="ws2007FederationHttpBinding"
          bindingConfiguration="IDBookIssuerIssuedTokenFederation"
          name="ApplicationWsHttpEndpoint" contract="GILabs.MetaFx.Application.Service.ISyncChangeService">
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>

    <diagnostics>
      <messageLogging logEntireMessage="true"
                      logMessagesAtServiceLevel="true"
                      logMessagesAtTransportLevel="true"
                      logMalformedMessages="true"
                      maxMessagesToLog="5000"
                      maxSizeOfMessageToLog="2000">
      </messageLogging>
    </diagnostics>
  </system.serviceModel>

  <system.webServer>

    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="500000000"></requestLimits>
      </requestFiltering>
    </security>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>

  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel" switchValue="All" propagateActivity="true">
        <listeners>
          <add name="traceListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData="C:\temp\Traces.svclog"/>
        </listeners>
      </source>
    </sources>
    <trace autoflush ="true" />
  </system.diagnostics>
</configuration>

Creating my service in Client:

_syncChangeService = ClientFactory.Current.Create<SyncChangeServiceClient, ISyncChangeService>(
                         ConfigurationManager.Instance.OrganizationName,
                         ConfigurationManager.Instance.ServiceManagerUserName,
                         ConfigurationManager.Instance.ServiceManagerUserPassword,
                         new EndpointAddress(ConfigurationManager.Instance.IdBookWSUrl),
                         new EndpointAddress(string.Format("{0}/Services/SyncChange.svc", ConfigurationManager.Instance.ServiceManagerUrl))
                     );
Was it helpful?

Solution

I found the problem! :D

The problem is in IdBookIssuerIssuedTokenBinding.CreateBindingElements().

I had overridden and not called the base:

public override BindingElementCollection CreateBindingElements()
{
    BindingElementCollection elements = new BindingElementCollection();

    elements.Add(this.security);
    elements.Add(this.transport);

    return elements;
}

Now I am doing this:

public override BindingElementCollection CreateBindingElements()
{
    BindingElementCollection elements = base.CreateBindingElements();

    var securityBindingElement = elements.Find<SecurityBindingElement>();
    elements.Remove(securityBindingElement);
    elements.Add(this.security);

    var transportBindingElement = elements.Find<HttpTransportBindingElement>();
    elements.Remove(transportBindingElement);
    elements.Add(this.transport);

    return elements;
}

And it works like a charm!

I can't explain why I need to call base. If someone could explain in the comments, that would be great!

OTHER TIPS

I've run into problems similar to this before. In your config file, try increasing the size for all instances of your following line (there were at least two):

ws2007HttpBinding.MaxBufferPoolSize = int.MaxValue;

Also, in your service, do the same here:

<ws2007FederationHttpBinding>
    <binding name="IDBookIssuerIssuedTokenFederation" closeTimeout="00:10:00" openTimeout="00:10:00" 
... **maxBufferPoolSize="2147483647"**

It's a wee bit counter-intuitive, but the service will barf if it receives a response that is larger than it is configured to accept.

Hope that helps!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top