WCF webservice over basicHttpBinding with Streaming uses over 2 gigs of ram - c#

I have an IIS hosted WCF webservice, it has two endpoints, one for wsHttpBinding, the other is for basicHttpBinding. I use basicHttpBinding so I can set the transferMode to "Streamed" so I can stream files. This service also is under SSL and needs a client certificate to connect to.
When I call the wsHttpBinding services and everything is fine. When I call the basicHttpBinding services to stream a file it will use all the free ram (the machine has 2.5 gigs) and then hits the page file and throws hard faults. All these hard faults and disk swapping causes the services to time out since it's taking longer than 60 seconds to return.
Below is the function that I am calling that is eating all the ram and timing out
[OperationBehavior]
public Stream GetOrderResults(string clientName, string userName, string password, string institutionId, Guid orderId, string fileName)
{
var fileStream = new System.IO.FileStream(#"\\iwebdev510\Relateprod\TDHub\Temp\TDTestClient\bob.xml", FileMode.Open);
return fileStream;
}
The configuration file for the client calling the webservice looks like this:
<?xml version="1.0"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
<system.serviceModel>
<!-- REMOVE THE BEHAVIORS FOR DEV TESTING -->
<behaviors>
<endpointBehaviors>
<behavior name="ClientCertBehavior">
<clientCredentials>
<clientCertificate x509FindType="FindByThumbprint" findValue="8b08c6e6e356a345212e539979fbcaca337aae8a"/>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<!--Dev Endpoints With Certs-->
<endpoint address="https://<obfuscated>/secure/TDHubService.svc"
behaviorConfiguration="ClientCertBehavior"
binding="wsHttpBinding"
bindingConfiguration="wsTDHubServiceBindingTLS"
contract="MortgageCadence.External.TDHub.Protocols.Contracts.Services.ITDHubService" />
<endpoint address="https://<obfuscated>/secure/TDHubFileTransferService.svc"
behaviorConfiguration="ClientCertBehavior"
binding="basicHttpBinding"
bindingConfiguration="basicTDHubFileTransferServiceBindingTLS"
contract="MortgageCadence.External.TDHub.Protocols.Contracts.Services.ITDHubFileTransferService" />
</client>
<bindings>
<basicHttpBinding>
<binding name="basicTDHubFileTransferServiceBinding" maxReceivedMessageSize="2147483647"
transferMode="Streamed">
<readerQuotas maxDepth="64" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None" />
</binding>
<binding name="basicTDHubFileTransferServiceBindingTLS" maxReceivedMessageSize="2147483647"
transferMode="Streamed">
<readerQuotas maxDepth="64" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</basicHttpBinding>
<wsHttpBinding>
<binding name="wsTDHubServiceBinding" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="64" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None" />
</binding>
<binding name="wsTDHubServiceBindingTLS" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="64" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
</configuration>
I can provide a screen shot of the computers resource monitor being eaten by w3wp.exe, but I can't attach it ATM because my reputation is not high enough.
I have discovered that if I change the transfer mode from "Steamed" to "Buffered" in the binding it completely solves the memory issue, but this appears to be counter to what the documentation suggests. The documentation makes it sound like if you choose "buffered" it will load the entire file into memory before sending, but I've sent a 700 meg file and the memory didn't change in buffered mode.

Related

Insufficient Memory Exception in WCF Large File Uploading

I am trying to upload large files(>10GB) using WCF.
The Service Web.config is as below
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding" maxBufferPoolSize="2147483647000000" maxReceivedMessageSize="2147483647000000" transferMode="Streamed">
<readerQuotas maxDepth="200000000" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:42890/Service1.svc" behaviorConfiguration="endpointBehavior"
binding="basicHttpBinding"
contract="UploadFileService.IService1" name="BasicHttpBinding" />
</client>
And the client side web.config as below
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding" closeTimeout="10:00:00" openTimeout="10:00:00"
receiveTimeout="10:00:00" sendTimeout="10:00:00" maxBufferPoolSize="2147483647000000"
maxReceivedMessageSize="2147483647000000" />
</basicHttpBinding>
</bindings>
I got insufficient memory exception when I run the code, How can I solve it?
In your solution, target x64 instead of Any CPU. This will allow more memory allocation.
However, depending on your solution, you might be able to Stream the file to disk, not requiring to use so much memory.

The maximum string content length quota (8192) has been exceeded.Increase the MaxStringContentLength property on the XmlDictionaryReaderQuotas

I got the following error when i passed an entity object to a WebService
The maximum string content length quota (8192) has been exceeded while reading XML data. This quota may be increased by changing the MaxStringContentLength property on the XmlDictionaryReaderQuotas object used when creating the XML reader
I tried to solve this problem by giving the below code in webconfig of Webservice,but the error still remains. Can anyone Help!!!!!
<bindings>
<wsHttpBinding>
<binding name="MyService" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
You have to set the maximum string content length quota on the server and the client. So check your client config. If that is not working, check if you are using the right binding.
Your server side Web config allows large strings, but you also need to modify your client side ServiceReferences.ClientConfig file to reflect that.
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="Binding_MyService">
<binaryMessageEncoding />
<httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="yourserviceurlhere"
binding="wsHttpBinding" bindingConfiguration="Binding_MyService"
contract="yourcontracthere" name="MyService" />
</client>
</system.serviceModel>

Sending object to WCF service. MaxStringContentLength (8192 bytes) exceeded when deserializing

I created a simple WCF web service that has one method: SubmitTicket(flightticket ft, string username, string password)
On the client side, I have an application for filling out a form (a flight ticket) and sending it to this newly created web service. When this flightticket object exceeds 8192bytes I get the following error:
"There was an error deserializing the object of type flightticket. The maximum string content length quota (8192) has been exceeded while reading XML data. This quota may be increased by changing the MaxStringContentLength property on the XmlDictionaryReaderQuotas object used when creating the XML reader"
I did some research online and found that I have to set the MaxStringContentLength in the web.config (server) and app.config (client) to a higher number. Problem is, I've tried every possible combination of settings in both config files from reading various blogs and sites, but it STILL fails on that same error!
I have attached my client and server config code (as it is at the moment, it has gone through many many many changes over the day with no success).
One thing I noticed is that the configuration.svcinfo file on my client application seems to always shows 8192 for MaxStringContentLength when I update the service reference. It appears to take all the default values even if I explicitly set the binding properties. Not sure if that is related to my problem at all, but worth mentioning.
Here is the applicable app.config/web.config code for defining the endpoint bindings:
<<<<< CLIENT >>>>>
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
</configSections>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IFlightTicketWebService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="65536" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://xx.xx.xx/xxxxxxxx.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IFlightTicketWebService"
contract="FlightTicketWebService.IFlightTicketWebService"
name="BasicHttpBinding_IFlightTicketWebService" />
</client>
</system.serviceModel>
</configuration>
<<<<< SERVER >>>>>
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="GSH.FlightTicketWebService.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<system.web>
<httpRuntime maxRequestLength="16384"/>
<compilation debug="true" targetFramework="4.0"/>
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/>
</system.web>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IFlightTicketWebService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="65536" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
<services>
<service name="FlightTicketWebService">
<endpoint
name="FlightTicketWebServiceBinding"
address="http://xx.xx.xx/xxxxxxxxxxx.svc"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IFlightTicketWebService"
contract="IFlightTicketWebService"/>
</service>
</services>
</system.serviceModel>
<system.webServer>
I think the problem is that your service is not picking up its config because you have set the service name to be FlightTicketWebService whereas I would guess that the actual type is in a namespace. Fully qualify the service name with the namespace and it should pick up your config
Essentially this is a by-product of the WCF 4 default endpoint functionality that if it finds no matching config it puts endpoints up with the default config
This is the answer! I have searched everywhere the solution to this problem in WCF 4.0, and this entry by Richard Blewett was the final piece of the puzzle.
Key things learned from my research:
if the exception is thrown by the service, then only change the
Server Web.config file; don't worry about the client
create a custom basicHttpBinding:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="customBindingNameForLargeMessages">
add the larger readerQuota values (largest possible shown here, adjust to taste)
<binding name="customBindingNameForLargeMessages"
maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
create a service entry, with an endpoint that maps to the custom binding. The mapping happens when the endpoint's bindingConfiguration is the same as the binding's name:
Make sure the service name and the contract value are fully qualified - use the namespace, and the name of the class.
<system.serviceModel>
<services>
<service name="Namespace.ServiceClassName">
<endpoint
address="http://urlOfYourService"
bindingConfiguration="customBindingNameForLargeMessages"
contract="Namespace.ServiceInterfaceName"
binding="basicHttpBinding"
name="BasicHTTPEndpoint" />
</service>
</services>

Transferring 5 megabytes file using wcf

I am trying to use wcf for transferring a file larger then 5 mega.(i cant use streeaming for now it demands major changes to running code).
I configured the server and the client to the maximum settings and still i get the exception of maximum length.
Here is my server web.config:
<system.serviceModel>
<diagnostics>
<messageLogging logMalformedMessages="true" logMessagesAtServiceLevel="true"
logMessagesAtTransportLevel="true" />
</diagnostics>
<services>
<service name="xxx.xxx.Service">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="xxx"
contract="xxx.xxx.IService" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="b2bservice" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
transferMode="Buffered" useDefaultWebProxy="true">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
<client />
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true" />
And here is the client app.config:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="xxx"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService"
contract="BService.IBService" name="BasicHttpBinding_IService" />
</client>
My trace Logging is:
Maximum request length exceeded.
System.ServiceModel.CommunicationException, System.ServiceModel,
Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089`
Any thoughts?
You are not resetting the default 4MB limit properly.
Try this: http://smehrozalam.wordpress.com/2009/01/29/retrieving-huge-amount-of-data-from-wcf-service-in-silverlight-application/
Set maxRequestLength in httpRuntime section in Web.config
HttpRuntime configuration element
You'll need to increase the max request length by changing the following setting in web.config
<configuration>
<system.web>
<httpRuntime maxRequestLength="32768" />
</system.web>
</configuration>
The value is in KB.
You can use tracing to get more details about your problem and fix it or give use exact error message.

WCF communication problem

In my WCF application I receive an image in base64String format along with some other images..
In order to test my application I have created a small .aspx page which will
send firstname, last name and base64string(image:size 10Kb) to the WCF Sevice.
I am getting the error
"The formatter threw an exception while trying to deserialize the message:
Error in deserializing body of request message for operation 'SaveData'.
The maximum string content length quota (8192) has been exceeded while reading XML data.
This quota may be increased by changing the MaxStringContentLength property on the
XmlDictionaryReaderQuotas object used when creating the XML reader. Line 1, position 15301."
If I send the strings without the base64string(image) i was able to debug the wcf Service code.
But if I add the base64String I am getting this error.
I have increased all binding values("maxReceivedMessageSize") and other values to maximum.
Still I am getting this error. Here is my web.config for client and Service.
Thanks and I really appreciate your help.
Client Web.config
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IRESTService1" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647"
maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:10255/RESTService1.svc" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IRESTService1" contract="ServiceReference1.IRESTService1"
name="BasicHttpBinding_IRESTService1" />
</client>
</system.serviceModel>
Service web.config
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicBinding1" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="RESTService1">
<endpoint address=""
binding="basicHttpBinding" name="MainHttpPoint" contract="RESTService1" bindingConfiguration="BasicBinding1" />
</service>
</services>
<!--<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>-->
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
Add these lines inside Binding tag in web.config file
<binaryMessageEncoding maxReadPoolSize="2147483647" maxWritePoolSize="2147483647">
<readerQuotas maxArrayLength="2147483647" maxStringContentLength="2147483647" maxBytesPerRead="2147483647" />
</binaryMessageEncoding>
<httpTransport decompressionEnabled="True" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"/>
MSDN : binaryMessageEncoding
hope this help

Categories