IIS Presumably blocks outgoing WCF messages over a certain size - c#

I have ported over an old application to asp.net core 6. Its an API that gets incoming requests and communicates over net.tcp to a wcf service that i have no control over. The bindings and xml reader quotas are all set high. Everything works ok when I transfer simple messages. However one feature requires me to send base64 encoded images to the wcf service. And this is when i get this error.
The socket was aborted because an asynchronous receive from the socket did not complete within the allotted timeout of 10675199.02:48:05.4775807. The time allotted to this operation may have been a portion of a longer timeout.
In my testing an image of 8kb goes through normally but one on 16kb and above does not go through.
Further more. If i launch my asp.net application via .exe file instead of IIS then everything goes through fine. This leads me to believe that something in IIS blocks my xml transfer. I have tried modifying "uploadReadAheadSize" after googling but that had no effect. Im at a loss here as i would like to use IIS to host this API.
Ive tries to enable tracing but cannot get that working on my solution.
Current binding looks like this, although ive tried increasing buffer sizes also, but i removed to make it more like how it looks on the service side.
NetTcpBinding binding = new NetTcpBinding();
binding.TransferMode = TransferMode.Streamed;
binding.Security.Mode = SecurityMode.None;
binding.ReceiveTimeout = TimeSpan.FromSeconds(20);
binding.SendTimeout = TimeSpan.FromSeconds(20);
binding.MaxReceivedMessageSize = 650000;
XmlDictionaryReaderQuotas myReaderQuotas = new XmlDictionaryReaderQuotas();
myReaderQuotas.MaxStringContentLength = 2147483647;
myReaderQuotas.MaxNameTableCharCount = 2147483647;
myReaderQuotas.MaxArrayLength = 2147483647;
myReaderQuotas.MaxBytesPerRead = 2147483647;
myReaderQuotas.MaxDepth = 64;

This error may be caused by the default limits defined in service configuration are too low (MaxItemsInObjectGraph, MaxReceivedMessageSize, MaxBufferPoolSize, MaxBufferSize, MaxArrayLength).
you can try fix by increasing the values in the config file.
<binding name="MyCoolBinding" maxreceivedmessagesize="10000000" maxbuffersize="10000000" maxbufferpoolsize="10000000">
More information you can refer to this link: http://nerdwords.blogspot.com/2008/01/wcf-error-socket-connection-was-aborted.html.

Related

Set ServiceBehavior on channelfactory WCF Net.Pipe

I am hosting a Net.Pipe WCF service from a forms application, which runs on a server for mostly internal calculations. To improve on this I was tasked with creating a Rest shell around this service so it becomes reachable from outside of the server. I managed to connect to this service with ease, but as soon as I drop it on the live server My rest shell can no longer connect, I tried debugging this, but the main error message that gets logged is:
The server was unable to process the request due to an internal
error. For more information about the error, either turn on
IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute
or from the serviceDebug configuration behavior) on the server in
order to send the exception information back to the client, or turn on
tracing as per the Microsoft .NET Framework SDK documentation and
inspect the server trace logs.
Thing is that I connect to this service from code and I cannot figure out how to either convert the way I connect to a service host so I can add the Service behavior or add the behavior to my channel factory.
NetNamedPipeBinding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
ServiceDebugBehavior behavior = new ServiceDebugBehavior { IncludeExceptionDetailInFaults = true };
EndpointAddress ep = new EndpointAddress("net.pipe://localhost/IPCService");
ChannelFactoryfactory = new ChannelFactory<RadanWrapper.IRadanContract>(binding);
// This line doesn't work
factory.Endpoint.EndpointBehaviors.Add(behavior as IServiceBehavior);
_channel = factory.CreateChannel(ep);
So the question is either: How do I connect the behavior to the channel factory, or alternatively, how can I connect to this net.pipe service through service host. (I am still looking into the second options)
I found the problem, I tried adding the behavior to the rest shell (connecting end), while it should have been added to the forms application (Hosting end) that was hosting the net.Pipe WCF
ServiceHost serviceHost = new ServiceHost(typeof(IPCService));
NetNamedPipeBinding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
// Create new behavior, remove any existing behaviors and add this new one.
var behavior = new ServiceDebugBehavior { IncludeExceptionDetailInFaults = true };
serviceHost.Description.Behaviors.Remove(typeof(ServiceDebugBehavior));
serviceHost.Description.Behaviors.Add(behavior);
serviceHost.AddServiceEndpoint(typeof(IPCService), binding, "net.pipe://localhost/IPCService");
serviceHost.Open();
Good thing I now got an actually working error message, turns out I was missing a specific dll that didn't get build correctly during deployment to the server.

WCF Channel: Server not responding after 10 minutes

I created an architecture formed by a client and a server those communicates on a WCF Channel in localhost, all works fine, but if there is no activity (requests from client) between the two ones for more than 10 minutes the server doesn't respond anymore. The connection is still alive but simply server is not responding to client request, so the client must disconnect and reconnect for being able to send request to the server. Maybe I let some parameters slip.
The address I used is: net.tcp://localhost:8080/ICS;
Channel type: duplex;
The problem here is in receiveTimeout. The service host uses this timeout to determine when to drop idle connections. If no message is received within the configured time span the connection is closed. By default it is 10 minutes.
Update, ReliableMessaging is not enabled therefore edit InactivityTimeout makes no sense
Whereas changing ReceiveTimeout parameter of my binding settings solves the problem.
My code:
var bind = new NetTcpBinding(); // my binding instance
var relSessionEnabled = bind.ReliableSession.Enabled; // this is false
var inactivityTimeout = bind.ReliableSession.InactivityTimeout; // this is 10 minutes
bind.ReceiveTimeout = TimeSpan.MaxValue; // this was 10 minutes before this instructuion

Add Header to WCF RequestSecurityToken Message

I'm attempting to set up a client (Web Application) and service (WCF Service) that will communicate using a WSHttpBinding. It appears that in order to use this binding the client sends preliminary messages to set up the channel.
Between the client and the service exists a service bus which is routing on a custom header. The message, when using BasicHttpBinding security, routes without issue.
My question is: Is there any way to add the same custom header to the preliminary RequestSecurityToken message?
Thank you in advance.
This has been resolved.
Unfortunately, according to the MSDN documentation, a service using WCF transport security cannot go through a router, nor should either, service nor client, be located on the internet (https://msdn.microsoft.com/en-us/library/ff648863.aspx#TransportSecurity).
We wanted to violate both 'principles'.
So in order to cut down the messages, from five calls and responses to one, we switched to Message Security and turned off EstablishSecurityContext and NegotiateServiceCredential. - This had to be done on both the Service and Client configuration settings.
In addition to this, a noteworthy tip may be that, in order to point the service to our service bus, we changed theClientViaBehavior of the service on the Client Side.
Turn off EstablishContext and NegotiateServiceCredential:
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.EstablishSecurityContext = false;
binding.Security.Message.NegotiateServiceCredential = false;
Point client to Service Bus:
serviceClient.Endpoint.EndpointBehaviors.Add(new ClientViaBehavior(new Uri("http://url/WCFService/ServiceName.svc")));

User request queue in WCF

I have a WCF service which creates a number of files at a server location doing various calculation on seed file depending upon the params given. The problem is that, the when 2 or more clients try to do calculation on same seed file, it is returning error. The cause is simply due to read/write access by multiple users at a time.
So I want to create a user request queue in WCF from where server does its calculation one at a time and returns calculated response to the user. The problem is I dont know how to do it.
I have not implemented any request queue technique in WCF before. Does anyone know how to implement this in WCF Sevcices. I cannot do threading as calculation depends upon the file I/O so handling one request at a time is only one solution at this time.
Any tutorial or video tutorial will be highly appreciated.
Finally I did it.
Here I am posting my soluton for other users who may be new to the WCF request queuing.
At first, we need to implement the throttling settings in WCF host file.
Throttling can be done in two ways (Either way is OK):
Config file
Code
Throttling settings in config file as follows:
[behaviors]
[serviceBehaviors] [behavior name="throttlingBehavior"] [serviceThrottling maxConcurrentCalls="3" maxConcurrentInstances="3" maxConcurrentSessions="100"/] [/behavior]
[/serviceBehaviors]
[/behaviors]
Or throttling settings in code
using (ServiceHost host = new ServiceHost(typeof(SimpleService.SimpleS­ervice)))
{
ServiceThrottlingBehavior throttlingBehavior = new ServiceThrottlingBehavior { MaxConcurrentCalls = 3, MaxConcurrentInstances = 3, MaxConcurrentSessions = 100 };
host.Description.Behaviors.Add(throttlin­gBehavior);
host.Open();
Console.WriteLine("Host started # " + DateTime.Now.ToString());
Console.ReadLine();
}
With the above throttling settings a maximum of 3 concurrent calls are processed. In addition to maxConcurrentCalls property, maxConcurrentInstances and maxConcurrentSessions may also impact the number of calls processed concurrently.
Now after defining throttling behavior, we need to define concurrency mode in service contract as follows:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall,ConcurrencyMode=ConcurrencyMode.Multiple)]
public class Service:IService
{...
With these settings in placed, we can easily get the the request queuing in WCF service.

TimeoutException when TransferMode=Streamed

I inherited this huge application consisting of client and server code, and I'm trying to change the transfer mode for parts of our communication to 'streamed', to get around the really wasteful memory consumption that can occur in buffered mode and makes my client throw OOM exceptions, see also this answer.
The code goes something like this:
GZipMessageEncodingBindingElement gElement = new GZipMessageEncodingBindingElement();
HttpsTransportBindingElement hElement = new HttpsTransportBindingElement();
hElement.TransferMode = TransferMode.Streamed;
hElement.MaxBufferSize = int.MaxValue;
hElement.MaxBufferPoolSize = int.MaxValue;
hElement.MaxReceivedMessageSize = int.MaxValue;
CustomBinding binding = new CustomBinding();
binding.SendTimeout = new TimeSpan(0, 0, 60);
binding.Elements.Add(gElement);
binding.Elements.Add(hElement);
EndpointAddress address = new EndpointAddress(uri);
return new ChannelFactory<T>(binding, address).CreateChannel();
And the exception is a TimeoutException that suggests I increase the SendTimeout (which currently is set to 1 minute).
Update: However, there are 2 services that still work after setting the transferMode to streamed, I actually confirmed that they use GZIP/HTTPS by setting breakpoints in GZIPMessageEncoder.ReadMessage(Stream, ...). So for 2 services it breaks inside ReadMessage, for one service it doesn't. As far is I can tell, the services are configured identically, when it comes to ConcurrencyMode and InstanceContextMode.
Update 2: After configuring only the one service that didn't seem to work as Streamed and leaving the other 2 services buffered, it partly worked. So it is not the service as such that is bad, maybe some connection is getting in the way of other connections in Streamed mode, making them time-out.
If I delete just the 'TransferMode' line, everything is fine, and the test server never needs more than a second or so to respond, so just increasing the SendTimeout won't lead anywhere.
For this test, I only changed the client btw., as to my understanding, this setting should not affect the way client and server communicate, just the way that the application with the "streamed" setting processes the data.
Please be easy on me, I'm a total WCF newb, and although I have seen some caveats on the MSDN pages about the streamed transfer mode, a pointer at what to grep for in my code / configuration would be really helpful, otherwise it's just huge, many services, each with different transport settings etc.
Thanks!
I could not exactly figure out the cause of the issue, but I was able to fix the issue and getting rid of excessive memory consumption etc. by doing the following.
After getting rid of GzipMessageEncoder (see wcf conditional compression for how to replace it by IIS' builtin compression), which is a monstrosity (see my answer on WCF HttpTransport: streamed vs buffered TransferMode), it was easy to switch to streamed TransferMode: How can I prevent BufferManager / PooledBufferManager in my WCF client app from wasting memory?.

Categories

Resources