I get this error sending an uploaded, large excel file in a method call from the client web app to a web service in a .net 4.5 mvc wcf application. It worked before with the same file, but after securing the client / service connection with a client certificate I got this error:
The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:data. The InnerException message was 'There was an error deserializing the object of type System.Byte[]. The maximum array length quota (16384) has been exceeded while reading XML data. This quota may be increased by changing the MaxArrayLength property on the XmlDictionaryReaderQuotas object used when creating the XML reader. Line 1, position 2584463.'. Please see InnerException for more details.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ServiceModel.FaultException`1[[System.ServiceModel.ExceptionDetail, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]: The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:data. The InnerException message was 'There was an error deserializing the object of type System.Byte[]. The maximum array length quota (16384) has been exceeded while reading XML data. This quota may be increased by changing the MaxArrayLength property on the XmlDictionaryReaderQuotas object used when creating the XML reader. Line 1, position 2584463.'. Please see InnerException for more details.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[FaultException`1: The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:data. The InnerException message was 'There was an error deserializing the object of type System.Byte[]. The maximum array length quota (16384) has been exceeded while reading XML data. This quota may be increased by changing the MaxArrayLength property on the XmlDictionaryReaderQuotas object used when creating the XML reader. Line 1, position 2584463.'. Please see InnerException for more details.]
System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) +10733331
System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) +336
MyService.WebApp.ImportServiceRef.IImportService.Import(LoginContext lctx, Byte[] data, String filename) +0
After reading a lot about the issue on stackoverflow, I tried several things to increase all buffers and max-arguments in all bindings, but in the end still get the same error. Strange thing is that the setup worked before switching to client certificates. Any suggestions?
Client Web.config:
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=..."/>
<section name="system.identityModel.services" type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=..."/>
</configSections>
<appSettings>
...
</appSettings>
<location path="FederationMetadata">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
<system.web>
<globalization uiCulture="auto:de-DE" culture="auto:de-DE" requestEncoding="utf-8" responseEncoding="utf-8"/>
<customErrors mode="Off" defaultRedirect="Error"/>
<identity impersonate="false"/>
<sessionState mode="InProc" timeout="120"/>
<compilation debug="true" targetFramework="4.5"/>
<httpRuntime targetFramework="4.5" requestValidationMode="4.5" maxRequestLength="2097151"/>
<authentication mode="Windows"/>
<authorization>
<deny users="?"/>
</authorization>
<pages>
<namespaces>
...
</namespaces>
</pages>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
...
</handlers>
<httpProtocol>
</httpProtocol>
</system.webServer>
<runtime>
...
</runtime>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="SecuredBehaviour">
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
<clientCredentials>
<clientCertificate findValue="CertAzusClientTeststage" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My"/>
<serviceCertificate>
<authentication certificateValidationMode="PeerOrChainTrust"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="secureBinding" maxBufferPoolSize="2147483647" maxBufferSize="524288" maxReceivedMessageSize="2147483647">
<security mode="Transport" />
<readerQuotas
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxDepth="2147483647"
maxNameTableCharCount="2147483647"
maxStringContentLength="2147483647" />
</binding>
</basicHttpBinding>
<wsHttpBinding>
<binding name="secureBindingWs" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:15:00" sendTimeout="00:15:00"
messageEncoding="Text" textEncoding="utf-8"
useDefaultWebProxy="true"
maxBufferPoolSize="2147483647" maxBufferSize="524288" maxReceivedMessageSize="2147483647"
>
<readerQuotas
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxDepth="2147483647"
maxNameTableCharCount="2147483647"
maxStringContentLength="2147483647" />
</binding>
<binding name="wsHttpEndpointBinding" sendTimeout="12:00:00"
maxBufferPoolSize="2147483647" maxBufferSize="524288" maxReceivedMessageSize="2147483647"
>
<security mode="Message">
<message clientCredentialType="Certificate"/>
</security>
<readerQuotas
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxDepth="2147483647"
maxNameTableCharCount="2147483647"
maxStringContentLength="2147483647" />
</binding>
</wsHttpBinding>
</bindings>
<protocolMapping>
<add binding="basicHttpBinding" scheme="https" bindingConfiguration="secureBinding"/>
<add binding="wsHttpBinding" scheme="https" bindingConfiguration="secureBindingWs"/>
</protocolMapping>
<client>
<endpoint address="http://server-xyz/Service/AntragService.svc"
binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding"
contract="AntragServiceRef.IAntragService" name="WSHttpBinding_IAntragService" behaviorConfiguration="SecuredBehaviour">
<identity>
<dns value="CertAzusClientTeststage"/>
</identity>
</endpoint>
<endpoint address="http://server-xyz/Service/ImportService.svc"
binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding"
contract="ImportServiceRef.IImportService" name="WSHttpBinding_IImportService" behaviorConfiguration="SecuredBehaviour">
<identity>
<dns value="CertAzusClientTeststage"/>
</identity>
</endpoint>
<endpoint address="http://server-xyz/Service/ReportService.svc"
binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding"
contract="ReportServiceRef.IReportService" name="WSHttpBinding_IReportService" behaviorConfiguration="SecuredBehaviour">
<identity>
<dns value="CertAzusClientTeststage"/>
</identity>
</endpoint>
<endpoint address="http://server-xyz/Service/SettingsService.svc"
binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding"
contract="SettingsServiceRef.ISettingsService" name="WSHttpBinding_ISettingsService" behaviorConfiguration="SecuredBehaviour">
<identity>
<dns value="CertAzusClientTeststage"/>
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
Service Web.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=..." requirePermission="false" />
</configSections>
<appSettings>
...
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" maxRequestLength="2097151"/>
<globalization culture="de-DE" uiCulture="de-DE" />
</system.web>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding
maxBufferPoolSize="2147483647" maxBufferSize="524288" maxReceivedMessageSize="2147483647">
<readerQuotas
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxDepth="2147483647"
maxNameTableCharCount="2147483647"
maxStringContentLength="2147483647" />
</binding>
<binding
maxBufferPoolSize="2147483647" maxBufferSize="524288" maxReceivedMessageSize="2147483647"
name="secureBinding">
<security mode="Transport" />
<readerQuotas
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxDepth="2147483647"
maxNameTableCharCount="2147483647"
maxStringContentLength="2147483647" />
</binding>
</basicHttpBinding>
<wsHttpBinding>
<binding name="wsHttpEndpointLokal" sendTimeout="00:05:00"
maxBufferPoolSize="2147483647" maxBufferSize="524288" maxReceivedMessageSize="2147483647" >
<readerQuotas
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxDepth="2147483647"
maxNameTableCharCount="2147483647"
maxStringContentLength="2147483647" />
</binding>
<binding name="wsHttpEndpointBindingSecured" sendTimeout="00:05:00"
maxBufferPoolSize="2147483647" maxBufferSize="524288" maxReceivedMessageSize="2147483647" >
<security mode="Message">
<message clientCredentialType="Certificate"/>
</security>
<readerQuotas
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxDepth="2147483647"
maxNameTableCharCount="2147483647"
maxStringContentLength="2147483647" />
</binding>
<binding name="secureBindingWs" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:15:00" sendTimeout="00:15:00"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
maxBufferPoolSize="2147483647" maxBufferSize="524288" maxReceivedMessageSize="2147483647" >
<readerQuotas
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxDepth="2147483647"
maxNameTableCharCount="2147483647"
maxStringContentLength="2147483647" />
</binding>
<binding name="wsHttpEndpointBinding" sendTimeout="12:00:00"
maxBufferPoolSize="2147483647" maxBufferSize="524288" maxReceivedMessageSize="2147483647" >
<security mode="Message">
<message clientCredentialType="Certificate"/>
</security>
<readerQuotas
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxDepth="2147483647"
maxNameTableCharCount="2147483647"
maxStringContentLength="2147483647" />
</binding>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="SecuredServiceBehaviour" name="MyApp.Service.AntragService">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBindingSecured" contract="MyApp.Common.Service.IAntragService"/>
</service>
<service behaviorConfiguration="SecuredServiceBehaviour" name="MyApp.Service.ImportService">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBindingSecured" contract="MyApp.Common.Service.IImportService"/>
</service>
<service behaviorConfiguration="SecuredServiceBehaviour" name="MyApp.Service.ReportService">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBindingSecured" contract="MyApp.Common.Service.IReportService"/>
</service>
<service behaviorConfiguration="SecuredServiceBehaviour" name="MyApp.Service.SettingsService">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBindingSecured" contract="MyApp.Common.Service.ISettingsService"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="SecuredServiceBehaviour">
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="PeerOrChainTrust"/>
</clientCertificate>
<serviceCertificate findValue="CertAzusClientTeststage" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"/>
</serviceCredentials>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="SecuredBehaviour">
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
<clientCredentials>
<clientCertificate findValue="CertAzusClientTeststage" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My"/>
<serviceCertificate>
<authentication certificateValidationMode="PeerOrChainTrust"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
<add binding="wsHttpBinding" scheme="https" bindingConfiguration="secureBindingWs"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<client>
<endpoint
address="http://127.0.0.1/SecondService/StammdatenSvc.svc"
binding="wsHttpBinding"
bindingConfiguration="wsHttpEndpointBinding"
behaviorConfiguration="SecuredBehaviour"
contract="KV.Nordrhein.STMSAT.DataContract.ISatStammdatenSvc"
name="SatStammdatenSvc">
<identity>
<dns value="CertAzusClientTeststage"/>
</identity>
</endpoint>
</client>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<directoryBrowse enabled="true" />
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="198743680" />
</requestFiltering>
</security>
</system.webServer>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
<connectionStrings>
...
</connectionStrings>
</configuration>
The problem is the certificate signing. The signing encrypts the parts of the service method result. It does so by encrypting every primitive part of the result - if it is a list of strings, each string is encrypted seperatly. If it is a single big byte array like in my case, then the big byte array is encrypted as a whole, and the encryptor fails because it is bigger than 16 KByte. My current workaround is splitting the big byte array into a list of small byte array chunks (each 1 KByte), and now it works.
Another solution may be using streaming mode, but as cevauess wrote, streaming and message level security are not allowed together, and message level security is a requirement in my case.