Transmit DataMember with large Strings - c#

In a wcf-Application (.NET FW 4.0) hosted in IIS 8.0 I would like to send as parameter a complex DataMember with two large Strings. These strings can be up to 20 or more MB. First I used transferMode=Streamed, but I always got the error:
Additional information: The formatter threw an exception while trying to deserialize the message: There was an error while trying to
deserialize parameter http://tempuri.org/:request. The InnerException
message was 'There was an error deserializing the object of type
QCheckerService.Parameter. 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 set the readerQuotas all to max in the config file. But the error is concerning the XmlDictionaryReaderQuotas. Is there a way to avoid changing these latter quotas in the code?
I am a bit confused now what could be a suitable solution. Is the default transferMode=Buffered the right way to do this?
Or is the transmission of large strings impossible and I should use another way?
If I transmit small strings, it works. Here the additional configurations.
client app.config:
<system.serviceModel>
<client>
<endpoint address=http://localhost:12412/Service1.svc
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IQChecker"
contract="QCheckerService.IQChecker">
</client>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IQChecker"
maxBufferSize="2147483647"
maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647"
transferMode="Streamed">
<readerQuotas maxDepth="32"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
service web.config:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<bindings>
<basicHttpBinding>
<binding name="Basic"
maxReceivedMessageSize="2147483647"
maxBufferSize="2147483647"
maxBufferPoolSize="2147483647"
transferMode="Streamed">
<readerQuotas maxBytesPerRead="2147483647"
maxDepth="32"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Service Interface for relevant DataMember
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "MyMethod", BodyStyle = WebMessageBodyStyle.Bare)]
ReturnValue MyMethod (Parameter request);
[DataContract]
public class Parameter: IDisposable
{
[DataMember]
String String1;
[DataMember]
String String2;
public void SetString1(String drawing)
{
String1 = drawing;
}
public String GetString1()
{
return String1;
}
public void SetString2(String configuration)
{
String2 = configuration;
}
public String GetString2()
{
return String2;
}
public void Dispose()
{
}
Thank you for some advice.

In your service's config file, you have defined a basicHttpBinding with a name of "Basic". However, you have no endpoint for the service explicitly defined, so by default the framework will expose an endpoint with basicHttpBinding at the location of the service file. This default endpoint will use the default values for basicHttpBinding - in other words, the binding you defined is not used at all.
Two ways to fix this (in WCF 4.0+): You must either a) assign that binding by it's name to an explicit endpoint (which is also defined in the config file) or b) set it up as the default binding for that transport protocol.
For option a, you would add an endpoint to your service's config file:
<services>
<service name="Your service name">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="Basic"
contract="QCheckerService.IQChecker" />
</service>
</services>
For option b, you can make the configuration you specified as the default by ommitting the name attribute on the binding definition, like this:
<bindings>
<basicHttpBinding>
<binding maxReceivedMessageSize="2147483647"
maxBufferSize="2147483647"
maxBufferPoolSize="2147483647"
transferMode="Streamed">
<readerQuotas maxBytesPerRead="2147483647"
maxDepth="32"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
The above binding definition will be used for all services using that configuration file and basicHttpBinding.
For more information on default bindings, endpoints and behaviors, see A Developer's Introduction to Windows Communication Foundation 4

Related

Additional information: The remote server returned an unexpected response: (413) Request Entity Too Large

I'm getting this error in my WCF Service: Additional information: The remote server returned an unexpected response: (413) Request Entity Too Large.
I tried to increase maxReceivedMessageSize to 2147483647 but it still doesn't work. Then, I measured the size of my file and I realized that it has 10 Kb.
Do you guys have any idea of what it might be?
I'm sending you a copy of my code:
Here, I'm basically sending a list of 1o Kb for the business logic layer (WCF service)
else if (comboBoxReason.Text == "Antecipação indevida - automática")
{
AdjustmentAmount = 0;
using (Stream s = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(s, AnticipationAdjustment);
long size = s.Length;
}
AdjustmentAmount = Decimal.Round(FinancialAdjustmentsCalculations.AnticipationAutomaticRate(AnticipationAdjustment), 2); //THE ERROR IS HERE
textBoxAdjustment.Text = ValorAjuste.ToString();
AnticipationAdjustment.Clear();
}
That is my Web.Config from the Business Logic Layer (Ext)
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IInt" closeTimeout="01:00:01" openTimeout="01:00:01"
receiveTimeout="02:00:01" sendTimeout="09:00:00" maxBufferPoolSize="2147483647"
maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"/>
</basicHttpBinding>
And that is my App.Config from the interface:
<binding name="BasicHttpBinding_IExt"
closeTimeout="01:00:01"
openTimeout="01:00:01" receiveTimeout="02:00:01" sendTimeout="09:00:00"
maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" />
</basicHttpBinding>
I tried to add the readerQuotas and maxItemsInObjectGraph="2147483647", but it still doesn't work:
<binding name="BasicHttpBinding_IExt" closeTimeout="01:00:01"
openTimeout="02:00:01" receiveTimeout="01:00:01" sendTimeout="09:00:00"
maxBufferPoolSize="524288000" maxBufferSize="65536000" maxReceivedMessageSize="65536000">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:56296/ExtService.svc" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IExt" contract="ExtService.IExt"
name="BasicHttpBinding_IExt" behaviorConfiguration="Behaviors.EndpointBehavior" />
</client>
<behaviors>
<endpointBehaviors>
<behavior name="Behaviors.EndpointBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>

Getting "413 Request Entity Too Large" when talking to WCF service

I have a WCF service, Server, which accepts requests from a console application Client. When sending the data (which is relatively large), I get the following exception:
System.ServiceModel.ProtocolException: The remote server returned an unexpected response: (413) Request Entity Too Large. ---> System.Net.WebException: The remote server returned an error: (413) Request Entity Too Large.
I thought I had the limits correctly set in the config files, but apparently I'm mistaken?
Here's the relevant part of Server's app.config:
<system.serviceModel>
<services>
<service name="Services.Server">
<endpoint bindingConfiguration="LargeWeb" binding="webHttpBinding" contract="Interfaces.IServer" />
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="LargeWeb" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</webHttpBinding>
</bindings>
</system.serviceModel>
And here's Client's app.config:
<system.serviceModel>
<client>
<endpoint name="serverEndpoint" binding="webHttpBinding" bindingConfiguration="LargeWeb" contract="Interfaces.IServer" />
</client>
<bindings>
<webHttpBinding>
<binding name="LargeWeb" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</webHttpBinding>
</bindings>
</system.serviceModel>
And finally, this is how Client calls the Server's method:
using (var cf = new WebChannelFactory<IServer>("serverEndpoint", serverAddress))
{
var channel = cf.CreateChannel();
channel.SomeMethod(some, arguments);
}
What am I doing wrong?
Thank you for any help.
The issue was that Client was residing in a UnitTest project, and the issue arised while running a unit test. When running a unit test, only the UnitTest project's config file is taken into account, so the <service> parts of the Server config need to be copied into it.
This way, only one config file is ever used: both Server and Client read it for their configuration.
After that, things work fine.

C# WCF - net.tcp cannot find endpoint

I'm getting the following error message when trying to implement net.tcp WCF in C#:
"Could not find default endpoint element that references contract 'EventInterfaceService.IEventInterface'
in the ServiceModel client configuration section. This might be because no configuration file was found for your application,
or because no endpoint element matching this contract could be found in the client element."
On my client side I have the following code:
private void Initialize(string sInterfaceUrl, string sUserParticipantName)
{
EventInterfaceCallbackSink _callbackSink;
InstanceContext _instanceContext;
EndpointAddressBuilder _endpointAddressBuilder;
_callbackSink = new EventInterfaceCallbackSink();
_instanceContext = new InstanceContext(_callbackSink);
eventInterfaceClient = new EventInterfaceClient(_instanceContext); //Exception gets thrown here
EndpointIdentity edi = EndpointIdentity.CreateUpnIdentity(sUserParticipantName);
var endpointAddress = eventInterfaceClient.Endpoint.Address;
EndpointAddressBuilder newEndpointAddress = new EndpointAddressBuilder(endpointAddress);
newEndpointAddress.Uri = new Uri(sInterfaceUrl);
newEndpointAddress.Identity = edi;
eventInterfaceClient.Endpoint.Address = newEndpointAddress.ToEndpointAddress();
}
As you can see I get the EndPointAddress as sInterfaceUrl and the UserParticipantName as sUserParticipantName.
For the app.config I have the following:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicHttpBinding_Interface" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="Infinite" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
textEncoding="utf-8" useDefaultWebProxy="true" messageEncoding="Text">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" />
</security>
</binding>
</basicHttpBinding>
<netTcpBinding>
<binding name="NetTcpBinding_IEventInterface"/>
</netTcpBinding>
</bindings>
<client>
<endpoint address="http://localhost:8732/HTTPWCF/" binding="basicHttpBinding"
bindingConfiguration="basicHttpBinding_Interface" contract="InterfaceService.IInterface"
name="basicHttpBinding_Interface" />
<endpoint address="net.tcp://localhost:8733/NETTCPWCF/"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IEventInterface"
contract="EventInterfaceService.IEventInterface" name="NetTcpBinding_IEventInterface">
</endpoint>
</client>
</system.serviceModel>
When running this code in a stand-alone client (not the actual application) it works. I can't seem to find out what's wrong. Any tips would be great!
Thanks.
Edit: Is there any way configuring this purely at runtime, so I won't need the app.config? Regarding the comments below, config file may not be found or wrong one is being used.
Your comment mentioned that you are putting your app.config stuff into a class library. This won't be read. The app.config of the executing assembly gets read instead (or the web.config since this is ASP). You will need to add your relevant config info to the config file of the executing assembly (your ASP project).
Alternatively, you could use the static ConfigurationManager class to read in your specific app.config settings:
http://msdn.microsoft.com/en-us/library/system.configuration.configurationmanager.aspx

webHttpBinding having issue with posting 1MB xml file

I have webHttpBinding for wcf service. Can not post large xml file (1MB) to service getting following error RequestEntityTooLarge (413) is not one of the following: OK (200), Created (201), Accepted (202), NonAuthoritativeInformation (203), NoContent (204), ResetContent (205), PartialContent (206)"} System.Exception {System.ArgumentOutOfRangeException}
Here is configuration for wcf service..
<service name="abc" >
<endpoint address="http://localhost:8741/LTLInboundService/" binding="webHttpBinding" behaviorConfiguration="WebHttpBehaviour" contract="abc" name="webHttpBinding_LTLInboundService" >
</endpoint>
</service>
<webHttpBinding>
<binding name="webHttpBinding_LTLInboundService" closeTimeout="00:10:00"
openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"
allowCookies="false" bypassProxyOnLocal="false"
hostNameComparisonMode="StrongWildcard" maxBufferSize="2147483647"
maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
transferMode="Streamed"
useDefaultWebProxy="true">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</webHttpBinding>
Here is the code that is failing..
using (HttpClient client = new HttpClient("http://localhost:8741/LTLInboundService" + "/SendCompletionReports"))
{
// Initalise a response object
HttpResponseMessage response = null;
string responseFilePath = Path.Combine(#"c:\Samir\abc.xml");
string xmlData = System.IO.File.ReadAllText(responseFilePath);
// Create a content object for the request
HttpContent content = HttpContent.Create(xmlData, Encoding.UTF8, "text/xml");
// Make the request and retrieve the response
response = client.Post("http://localhost:8741/LTLInboundService" + "/SendCompletionReports", content);
// Throw an exception if the response is not a 200 level response
response.EnsureStatusIsSuccessful();
// Retrieve the content of the response for processing
response.Content.LoadIntoBuffer();
}
It fails on response.EnsureStatusIsSuccessful(); statement.
Any idea how to fix this in development and production ?
checkout this site and pay attention to how they have this section configured under the security section
Dealing with Larger Files in Asp.NET
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="2147483648" />
</requestFiltering>
</security>
</system.webServer>
You defined a webHttpBinding in your config file, but it's not being used by your service because you did not specify it in the bindingConfiguration attribute.
<service name="abc" >
<endpoint address="http://localhost:8741/LTLInboundService/"
binding="webHttpBinding"
behaviorConfiguration="WebHttpBehaviour" contract="abc"
name="webHttpBinding_LTLInboundService" >
</endpoint>
</service>
The name attribute is used for the endpoint configuration, but has no bearing on the binding configuration used. In your <endpoint> element add this:
bindingConfiguration="webHttpBinding_LTLInboundService"
so your defined endpoint will use the values for the binding specified, not the default.
Final endpoint would look like this:
<service name="abc" >
<endpoint address="http://localhost:8741/LTLInboundService/"
binding="webHttpBinding"
bindingConfiguration="webHttpBinding_LTLInboundService"
behaviorConfiguration="WebHttpBehaviour" contract="abc"
name="webHttpBinding_LTLInboundService" >
</endpoint>
</service>

The server has rejected the client credentials, WCF as Windows Service

I am able to connect to my WCF service with the Win-form application, however i am not able to do so with my windows service. Whenever i fire open() to the proxy it throws the following error
The server has rejected the client credentials
Inner Exception: System.Security.Authentication.InvalidCredentialException: The server
has rejected the client credentials.
---> System.ComponentModel.Win32Exception: The logon attempt failed
--- End of inner exception stack trace ---
at System.Net.Security.NegoState.ProcessAuthentication(LazyAsyncResult
lazyResult)
at System.Net.Security.NegotiateStream.AuthenticateAsClient(NetworkCredential
credential, ChannelBinding binding, String targetName, ProtectionLevel
requiredProtectionLevel, TokenImpersonationLevel
allowedImpersonationLevel)
at System.Net.Security.NegotiateStream.AuthenticateAsClient(NetworkCredential
credential, String targetName, ProtectionLevel
requiredProtectionLevel, TokenImpersonationLevel
allowedImpersonationLevel)
at System.ServiceModel.Channels.WindowsStreamSecurityUpgradeProvider.WindowsStreamSecurityUpgradeInitiator.OnInitiateUpgrade(Stream
stream, SecurityMessageProperty& remoteSecurity)
Tried searching for the solution, but none fitting my requirements, hence posted.
Please help...
Update 1:
#A.R., Tried using
client.ClientCredentials.Windows.AllowedImpersonationLevel =
System.Security.Principal.TokenImpersonationLevel.Impersonation;
but to no avail.
Update 2:
WCF service Configuration
<system.serviceModel>
<diagnostics performanceCounters="All" />
<bindings>
<netTcpBinding>
<binding name="myBindingForLargeData" maxReceivedMessageSize="5242880" maxConnections="10">
<readerQuotas maxDepth="64" maxStringContentLength="5242880" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
</binding>
</netTcpBinding>
</bindings>
<services>
<service behaviorConfiguration="WCFService.ServiceBehavior"
name="WCFService.CollectorService">
<endpoint address="" binding="netTcpBinding" bindingConfiguration="myBindingForLargeData"
name="netTcpEndPoint" contract="WCFService.ICollectorService" />
<endpoint address="mex" binding="mexTcpBinding" bindingConfiguration=""
name="mexTcpEndPoint" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8010/WCFService.CollectorService/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WCFService.ServiceBehavior">
<serviceMetadata httpGetEnabled="False"/>
<serviceDebug includeExceptionDetailInFaults="True" />
<serviceThrottling
maxConcurrentCalls="32"
maxConcurrentSessions="32"
maxConcurrentInstances="32"
/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Thanks for all your help. i got the answer after few days of some research and trial n error method :) well i know i am late to post the answer, but i think its better late than never.
So Here's the solution
i had to make some changes in my configuration files (both client & server)
On the client side i added <security> tag as shown below
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="netTcpEndPoint" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="5242880" maxBufferSize="5242880" maxConnections="15" maxReceivedMessageSize="5242880">
<readerQuotas maxDepth="32" maxStringContentLength="5242880" 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://xx.xx.xx.xx:8010/WCFService.CollectorService/" binding="netTcpBinding" bindingConfiguration="netTcpEndPoint" contract="CloudAdapter.CloudCollectorService.ICollectorService" name="netTcpEndPoint">
</endpoint>
</client>
</system.serviceModel>
and also added the same tag on the server side (WCF service configuration), as shown below
<bindings>
<netTcpBinding>
<binding name="myBindingForLargeData" maxReceivedMessageSize="5242880" maxConnections="10">
<readerQuotas maxDepth="64" maxStringContentLength="5242880" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
Hope this help a person in need :)
So the KEY is to make the <security> tag same over the client and the server configuration files.
Basically what is happening is that your calling service doesn't have the appropriate credentials, like you would have when calling from WinForms. What you need is some impersonation. It takes a bit of setting up, and is kind of annoying, but it will work.
Luckily MSDN has a nice little walkthrough.
http://msdn.microsoft.com/en-us/library/ms731090.aspx
There is some more general information on the topic here:
http://msdn.microsoft.com/en-us/library/ms730088.aspx
UPDATE:
Setting impersonation flags is not enough. You have to actually impersonate a credential to make it work. For example:
// Let's assume that this code is run inside of the calling service.
var winIdentity = ServiceSecurityContext.Current.WindowsIdentity;
using (var impContext = winIdentity.Impersonate())
{
// So this would be the service call that is failing otherwise.
return MyService.MyServiceCall();
}
Check out my answer on this post The server has rejected the client credentials.
Note the security node.
<bindings>
<netTcpBinding>
<binding name="customTcpBinding" maxReceivedMessageSize="20480000" transferMode="Streamed" >
<security mode="None"></security>
</binding>
</netTcpBinding>
</bindings>
What is the authentication mode you are using on your WCF Service? Seems like the winform app is running and providing the correct credentials while your windows service is not running with the specified privileges or the credentials being passed are not valid. Try to inspect your request using Fiddler when made from you winforms vs Windwos service and see the difference.
For me it helped to set on both sides (client + server) the security mode to None:
NetTcpBinding binding = new NetTcpBinding();
binding.Security.Mode = SecurityMode.None;
(Same answer as from spinner_den_g but in C# - no need to edit the app.config)

Categories