I have a windows service and a winform application that communicate between each other using WCF through TCP.
I sometimes have to exchange huge data and I encountered a CommunicationException on the client. Now I have trouble finding which property to change and where (on the server side or the client side?).
The problem occurs when the server is returning a value to the client that is a 2-uple (my own implementation) of two arrays of doubles: Tuple<Double[], Double[]> (both arrays have always the same length).
I have noticed that there is no error when the arrays have a length of 22 000, but the CommunicationException is thrown when arrays have a length of 44 000.
Here's my App.config file regarding the netTcpBinding part:
On the server:
<netTcpBinding>
<binding name="MyBindingConf"
maxReceivedMessageSize="5000000"
sendTimeout="00:05:00">
<readerQuotas maxArrayLength="67108864"
maxStringContentLength="67108864"/>
<security mode="None" />
</binding>
</netTcpBinding>
On the client:
<netTcpBinding>
<binding name="MyBindingConf"
maxReceivedMessageSize="5000000"
sendTimeout="00:59:00">
<readerQuotas maxArrayLength="67108864"
maxStringContentLength="67108864"/>
<security mode="None" />
</binding>
</netTcpBinding>
Could you point on which property to change and on which side?
P.S: It's not a timeout problem.
EDIT
I have now the same nettcpbindingconfiguration on both server and client:
<bindings>
<netTcpBinding>
<binding name="MyBindingConf"
maxReceivedMessageSize="2147483647"
maxBufferSize="2147483647"
maxBufferPoolSize="2147483647"
sendTimeout="00:30:00">
<readerQuotas maxDepth="32"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="4096"
maxNameTableCharCount="16384" />
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
And the same serviceBehavior:
<behaviors>
<serviceBehaviors>
<behavior name="Debug">
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
</serviceBehaviors>
</behaviors>
I then get a NetDispatcherFaultException on the client, advising me to increase maxArrayLength or maxItemsInObjectGraph. But for me, these values are already largely set for what I need to transfer and also set to the max values!
Here's the InnerException message:
The maximum array length quota (19502) or the maximum items in object graph quota has been exceeded while reading XML data. These quotas may be increased by changing the MaxArrayLength property on XmlDictionaryReaderQuotas or the MaxItemsInObjectGraph setting.
Any clue? Where does this 19 502 figure comes from?
On both, the server and client you have to configure the attribute of your binding, if you are exchanging large amounts of data between them. For example:
<binding name="LargeSettings" maxBufferSize="20000000" maxBufferPoolSize="20000000" maxReceivedMessageSize="20000000" closeTimeout="01:00:00" openTimeout="01:00:00" receiveTimeout="01:00:00" sendTimeout="01:00:00">
<readerQuotas maxDepth="32" maxStringContentLength="200000000" maxArrayLength="200000000" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None" />
</binding>
Work your way from the large values to find the one that suits you.
EDIT:
In Client side, you need to configure a behavior, and set that behavior in the client endpoint. Something like this:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="debug"> <dataContractSerializer maxItemsInObjectGraph="2147483647" />
</behavior>
</endpointBehaviors>
</behaviors>
And you set the behavior in the client endpoint:
<endpoint name="myEndpoint" behaviorConfiguration="debug">
Your other settings...
</endpoint>
Hope this helps.
Personally I would increase the MaxReceivedMessageSize, ensuring that maxBufferSize is also adjusted. These are the common areas that we have needed to adjust.
Here's a copy of a wsHttpBinding that I haved used in tests to successfully transfer huge chunks of data. I'm not saying these values are best practices, but they work to pass big chunks of data.
<binding name="WSHttpBinding_LargeData"
maxBufferPoolSize="524288"
maxReceivedMessageSize="99999999">
<readerQuotas
maxDepth="128"
maxStringContentLength="8192"
maxArrayLength="163840000"
maxBytesPerRead="4096"
maxNameTableCharCount="16384"
/>
</binding>
Did you try maxItemsInObjectGraph in your service behavior
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
Related
I am trying to create an windows application which will capture the screen periodically and convert the image as binary and send it through WCF service. WCF save this value in SQL database.
I cannot able to send through the WCF Service it throwing the error.
Other than the binary image, I send the user name only.
I checked the total service size is about 200kb, also in web.config file I gave allowed size of maxReceivedMessageSize="2000000"(2MB).
<bindings>
<basicHttpBinding>
<binding name="sslBinding" maxReceivedMessageSize="2000000" maxBufferSize="2000000">
<readerQuotas maxArrayLength="2000000" maxStringContentLength="2000000" />
<security mode="Transport" >
<transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
</security>
</binding>
</basicHttpBinding>
</bindings>
Tried:
Removed the binding name
Even gave maxReceivedMessageSize is 5MB.
I don't want to change basicHttpBinding to webHttpBinding, because other services are running in the same application.
I have referred the questions 30890220 and 44234761
Try using this for your binding:
<basicHttpBinding>
<binding maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text">
<readerQuotas maxDepth="2000000" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
I know you already modified maxReceivedMessageSize, so with the above you're also tampering with readerQuotas.
You can also try increasing the uploadReadAheadSize in IIS:
<location path="THENAMEOFTHESITEYOUHAVE" overrideMode="Allow">
<system.webServer>
<asp />
<serverRuntime uploadReadAheadSize="2147483647" />
</system.webServer>
I have a wcf service deployed under IIS 6.0. The service method accepts a list of objects and return the same list.
List<CustomObject> ProcessImageData(List<CustomObject> lstData)
The object may contain large amount of html data. The service currently takes hardly a few seconds to fulfill the request but I am getting a tons of following 2 exceptions.
"The request channel timed out while waiting for a reply after 00:00:59.9989999. Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding. The time allotted to this operation may have been a portion of a longer timeout."
"An error occurred while receiving the HTTP response to http://MyService.svc. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details."
Here is how my config files looks like.
web.Config (service) file
<service behaviorConfiguration="WcfServices.Service1Behavior" name="WcfServices.HtmlToImageService">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="LargeSizeMessages" contract="WcfServices.IHtmlToPngService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
<behaviors>
<serviceBehaviors>
<behavior name="WcfServices.Service1Behavior">
<serviceThrottling maxConcurrentCalls="1000" maxConcurrentSessions="1000" maxConcurrentInstances="1000"/>
<serviceMetadata httpGetEnabled="true"/>
<dataContractSerializer maxItemsInObjectGraph="6553500"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</behaviors>
<wsHttpBinding>
<binding name="LargeSizeMessages"
maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647">
<readerQuotas
maxDepth="32"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="4096"
maxNameTableCharCount="16384" />
</binding>
</wsHttpBinding>
Client Config file
<wsHttpBinding>
<binding name="WSHttpBinding_IHtmlToImageService" closeTimeout="00:10:00"
openTimeout="00:01: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"
allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" />
</security>
</binding>
</wsHttpBinding>
One of the exceptions propose to increase the sendTimeout vakue which is currently set to 1 minute. I increased it but it didn't seem to improve anything and I still get these exceptions.
Question:
Why am I getting these exceptions and what can I change to prevent this ?
Also, Here is an exception which is logged into Event Log on IIS server.
Exception Type: System.ArgumentException
Message: Parameter is not valid.
ParamName: NULL
Data: System.Collections.ListDictionaryInternal
TargetSite: Void .ctor(Int32, Int32, System.Drawing.Imaging.PixelFormat)
HelpLink: NULL
Source: System.Drawing
StackTrace Information
at System.Drawing.Bitmap..ctor(Int32 width, Int32 height, PixelFormat format)
at System.Drawing.Bitmap..ctor(Int32 width, Int32 height)
at WcfService.CreateBitmap(WebBrowser& browser) in C:_tfs\ImagingSystem\Development\Dev\Source\Wcf\WcfServices\HtmlToPngService\HtmlToPngService.svc.cs:line 126
You need to increase the timeout values in web.config (services), too. Something like this:
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IHtmlToImageService"
openTimeout="00:10:00"
closeTimeout="00:10:00"
sendTimeout="00:10:00"
receiveTimeout="00:10:00">
</binding>
</wsHttpBinding>
</bindings>
I suggest to review the following link:
https://msdn.microsoft.com/en-us/library/hh924831(v=vs.110).aspx
There can be a couple of things that can go wrong in this scenario. First, WCF is built to be very secure in its default configuration. That is why there is a limit to size of incoming requests. That limit is default rather small (65536 bytes). If your requests are larger than that, you need to configure the maxReceivedMessageSize and set it to the maximum number of bytes you want to support. Both on the server for incoming requests and the client for incoming responses. This is the likely cause for the second error, and you should be able to find a reference to this in the logging of your service.Next, IIS has its own limit to the size of incoming requests. The default value for this limit is 30000000 bytes (roughly 30MB). If your requests are larger than that, you should also increase that limit (see here for more information), as WCF will not even see the incoming request as IIS will block it before it gets there. The timeout error you are describing is likely to occur in this scenario, because IIS will not even bother to send a response as it thinks it is under attack when it gets requests that exceed the configured limit.Please think carefully about the values and bear in mind that maxReceivedMessageSize implicitly configures the buffer WCF will allocate to put the received message in. I've seen this value set to Int32.MaxValue in production systems. As a result the complete server could easily be brought down with a couple of huge concurrent requests, as the server tried to allocage 2GB of RAM to receive each of them.
you can first analyzed the exception. Do following exception Setting in visual studio and enable the "Common language Runtime exception".
mostly you can get the in depth details of exception using this.
I got this exception because one of the field is mandatory in my model which I am getting null in response and due to this on client side my object is not able to get deserialized properly.
I wanted to confirm something.
Below is how I am spinning up a call to my WCF web service in my ASP.NET application.
var xml = "my xml string";
var ep = new EndpointAddress("http://myendpoint");
xml = new Proxy.ServiceClient(new NetTcpBinding(), ep).getNewXML(new Proxy.CallContext(), xml);
My web config looks similar to below. My question is, even though these settings are in the web config, the fact that my calls above are newing up the a service client and fresh New TCP binding everytime tell me that these settings aren't being referenced. Is this correct based on above?
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_SCSService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="524288"
maxBufferSize="65536" maxConnections="10" maxReceivedMessageSize="65536">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://myendpoint"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_SCSService"
contract="Proxy.Service" name="NetTcpBinding_SCSService">
<identity>
<userPrincipalName value="user#user.com" />
</identity>
</endpoint>
</client>
</system.serviceModel>
That's correct. In this case, you are not using the configuration settings found in the config file.
Proxies typically derive from the abstract class ClientBase<T> which provides several different ways to create an instance of a client proxy. Some of the constructors listed will use all of the config file while others will attempt to use the config file to fill in the information that has not been explicitly supplied in the constructor. There are even constructor overloads which do not use the configuration file at all which ClientBase<TChannel>(Binding, EndpointAddress) is one of them.
If you wanted to use what was in the application configuration file, you could use:
var client = new Proxy.ServiceClient("NetTcpBinding_SCSService");
Calling my WCF service from my client silverlight app, I sometimes get a ProtocolException:
The content type text/html; charset=UTF-8 of the response message does not match the content type of the binding (text/xml; charset=utf-8).
Normally, I can step into the WCF service code and see it build an object then return it in serialised form.
But when the request exceeds ~4MB (as reported by Fiddler2), breakpoints in the WCF service code are not hit, and the content of the response (where the serialised object should be) is the HTML for the standard HTML page you'd see if you browsed to the service - the one that looks like this:
I can make any request fail or succeed by randomly adding characters to strings within the request object graph, or trimming chunks off the graph, so I'm fairly confident this is about the size of the request.
I'd be really grateful if anyone could explain why the response contains HTML, and even more grateful if you can tell me how to fix it.
I'm using VS2010. My server side config is:
<httpRuntime executionTimeout="10800"
maxRequestLength="10240" />
...
<system.web>
<httpRuntime maxRequestLength="2147483647" />
</system.web>
...
<serviceBehaviors>
<behavior name="StandardServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
...
<binding name="BasicHttpBinding_SilverlightService"
useDefaultWebProxy="false"
transferMode="Streamed"
bypassProxyOnLocal="true"
receiveTimeout="00:20:00"
sendTimeout="00:20:00"
maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647"
maxBufferPoolSize="2147483647">
<readerQuotas maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxDepth="2147483647"
maxNameTableCharCount="2147483647"/>
<security mode="TransportCredentialOnly">
<transport clientCredentialType="None"/>
</security>
</binding>
And client-side I have:
<binding name="BasicHttpBinding_SilverlightService" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<security mode="None" />
</binding>
Update
I've also tried removing the name from the binding tag, as suggested by this post.
Have you had a look at this post:
http://smehrozalam.wordpress.com/2009/01/29/retrieving-huge-amount-of-data-from-wcf-service-in-silverlight-application/
You obviously have the dataContractSerializer section covered, just wondering whether anything else is missing.
I'm having a WCF Service that uses wsHttpBinding. The server configuration is as follows :
<bindings>
<wsHttpBinding>
<binding name="wsHttpBinding" maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="None">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" establishSecurityContext="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
At the client side I'm including the Service reference of the WCF-Service. It works great if I have limited functions say 90 Operation Contract in my IService but if add one more OperationContract than I'm unable to Update the Service reference nor i'm able to add that service reference. In this article it's mentioned that by changing those config files(i.e devenv.exe.config, WcfTestClient.exe.config and SvcUtil.exe.config) it will work but even including those bindings in those config files still that error pops up saying
There was an error downloading 'http://10.0.3.112/MyService/Service1.svc/mex'.
The request failed with HTTP status 400: Bad Request.
Metadata contains a reference that cannot be resolved: 'http://10.0.3.112/MyService/Service1.svc/mex'.
There is an error in XML document (1, 89549).
The maximum nametable character count quota (16384) has been exceeded while reading XML data. The nametable is a data structure used to store strings encountered during XML processing - long XML documents with non-repeating element names, attribute names and attribute values may trigger this quota. This quota may be increased by changing the MaxNameTableCharCount property on the XmlDictionaryReaderQuotas object used when creating the XML reader. Line 1, position 89549.
If the service is defined in the current solution, try building the solution and adding the service reference again.
Any idea how to solve this????
Try the following:
In the installation directory of your Visual Studio where devenv.exe is located (e.g. C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE) add this section to the devenv.exe.cofig
<system.serviceModel>
<client>
<endpoint binding="customBinding" bindingConfiguration="largeServiceBinding" contract="IMetadataExchange" name="http" />
</client>
<bindings>
<customBinding>
<!-- NOTE: The binding name must be the same as specified in the config file of the wcf service -->
<binding name="largeServiceBinding" >
<textMessageEncoding>
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</textMessageEncoding>
<httpTransport transferMode="Buffered" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647"/>
</binding>
</customBinding>
</bindings>
</system.serviceModel>
in the app.config of your WCF-service add the same binding:
<bindings>
<customBinding >
<!-- NOTE: The binding name must be the same as specified in the devenv.exe.config file located ..\Common7\IDE folder of the VS installation directory -->
<binding name="largeServiceBinding" >
<textMessageEncoding>
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
</textMessageEncoding>
<httpTransport transferMode="Buffered" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647"/>
</binding>
</customBinding>
</bindings>
Note that the name attribute of the binding tags from the two files must match (e.g. largeServiceBinding)
Finally add the following mex endpoint into your service tag:
<endpoint address="mex" binding="customBinding" contract="IMetadataExchange" bindingName="testBinding" bindingConfiguration="largeServiceBinding" name="http"/>
this may look like this:
<services>
<service behaviorConfiguration="MyServiceBehavior"
name="MyService.MyService">
<endpoint address="" binding="wsHttpBinding" contract="MyService.IMyService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="customBinding" contract="IMetadataExchange" bindingName="testBinding" bindingConfiguration="largeServiceBinding" name="http"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8731/Design_Time_Addresses/MyService/MyService/" />
</baseAddresses>
</host>
</service>
</services>
I know it has been a while, but I got the same problem and found other (simpler) solution in codeproject
In the solution given there the values are set in the code rather than the .config file.
BasicHttpBinding binding = new BasicHttpBinding();
binding.Security.Mode = BasicHttpSecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
binding.MaxReceivedMessageSize = 50000000;
binding.ReaderQuotas.MaxArrayLength = 50000000;
binding.ReaderQuotas.MaxStringContentLength = 50000000;
binding.ReaderQuotas.MaxNameTableCharCount = 50000000;
EndpointAddress endpoint = new EndpointAddress(new Uri("https://server/EWS/Exchange.asmx"));
ExchangeServicePortTypeClient ews = new ExchangeServicePortTypeClient(binding, endpoint);
However, I changed the values in the relevant values in the .config file ( in both the <binding> and the <readerQuotas> sections) and solved the problem (rather than adding custom bindings):
<binding name="ITransactionProcessor" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="50000000" maxBufferPoolSize="524288" maxReceivedMessageSize="50000000"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="50000000" maxArrayLength="50000000"
maxBytesPerRead="4096" maxNameTableCharCount="50000000" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
I hope this will help somebody :)
One thing to recognize is that the message refers to the svcutil reader quotas not the service ones! Svcutil has a limit on how much metadata it can read. This limit can be changed with a config file. The solution is to create a config file for svcutil and place it in the same folder as the tool. Next time you run svcutil, the config file values will be taken into account.
http://geekswithblogs.net/claraoscura/archive/2007/08/20/114806.aspx
in your app.config or dll.config on the the client add:
<configuration>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="myMex" maxReceivedMessageSize="1024000"> <!-- modify this to avoid stupid error -->
<readerQuotas maxNameTableCharCount="163840" /> <!-- DO NOT touch this one -->
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
...
<client>
<endpoint binding="netTcpBinding" bindingConfiguration="myMex"
contract="IMetadataExchange" name="net.tcp" />
...
</client>
</system.serviceModel>
</configuration>
And there you go!
This is one of the really annoying things with WCF and as often google just yields you alot of bs. Wasted tons of time with this.