I am using a WCF Rest service which is called via JS ajax calls.
For some methods if an exception occurs it is caught and wrapped in a WebFaultException which has the status code set to 500 (Internal Server Error) and is thrown.
For the methods that have this behavior we have noticed that the whole call chain that generated an exception at some point is retried for a seemingly random number of times, sometimes it's just once, other times 3, 5, even 7 before the control is passed back to the client side and the error message is shown.
The WebService runs in IIS, and if i hook the debugger to it the retry logic doesn't occur anymore probably because VisualStudio halts the execution due to the unhandled exception.
At first this behavior seem'd to point to WS-ReliableMessaging but from the documentation it should be enabled explicitly. Anb we are using a WebHttpBinding, which afaik is not supported.
If I change the Exception behavior to not throw WebFaultException then this behavior stops.
Why is this happening?
Related
I am receiving a soap FAULT message through two way port and looks as below ,
<S:Fault xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns4="http://www.w3.org/2003/05/soap-envelope">
<faultcode>S:Status</faultcode>
<faultstring>Exception occured: TransactionRolledback</faultstring>
</S:Fault>
Error i am receiving : Only object types of 'System.Exception' can be added to the ESB Fault Message using this function
I am using separate exception block in orchestration using BTS.soap_envelope_1__1.Fault but still it fails ,
I want to catch this is ESB Exception and send to ESB Portal.
Follow the steps provided on this thread answer to catch the soap fault. Also as suggested adding steps here
To get the SOAP Fault into your orchestration:
On the Send port in BizTalk:
a) WCF Adapter Properties, Messages tab: Propagate Fault Message = true
b) WCF Adapter Properties, Messages tab: Inbound message body: Either use "soap:Body" or use a path that extracts your message OR /*[local-name()='Fault'] to get the SOAP fault
c) "Enable routing for failed messages" - this has no impact on the SOAP Fault. So you probably want it set to true to handle real transmission errors (non SOAP faults).
On the Send port within your orchestration
Select the operation & then "New Fault Message"
Set the message name to SoapFault (or whatever)
Set the message type to be the referenced schema: BTS.soap_envelope_1__2.Fault. (If this was a SOAP 1.1 operation you would use BTS.soap_envelope_1__1.Fault).
In the Scope around your Send operation
Add new exception handler
Select "Exception Object Type" to the port-name.operation-name.SoapFault you created in step 2
Specify the object name, e.g. Fault
Fault is now the XML of the SOAP Fault & you can use XPath to get the Fault Reason and Message elements.
Now, if a SOAP Fault occurs, no "exception" is shown in the BizTalk tracked message events view - it just shows that your orchestration receives the SOAP fault message. But inside your orchestration the message is treated as an exception and your "SoapFault" exception handler is called. You get a "FaultReceiveException".
Notes
1) The BizTalk Send Port tranmission retries option does not take effect if a SOAP fault occurs, because this is no longer viewed as a transmission failure. This is unfortunate, since the SOAP fault might be occuring due to a temporary problem at the target service & on retry the request might work.
2) Because the SOAP fault is not viewed by BizTalk as an error, your orchestration needs to log the message if you want to use routing of failed messages
3) You still need an exception handler for XlangSoapException's (i.e. System.Web.Services.Protocols.SoapException) and/or general exceptions, since these still occur for transmission errors (target server down, etc)
Because of (3), you will probably still want to specify "Enable routing for failed messages" to prevent suspended messages from occuring.
In my example I just received the soap:Fault part of the message, but you can pick up the entire soap:Envelope if needed.
I have created an WCF service hosted inside a normal Windows service. This service is deployed to customers and set up on their servers. Therefore (afaik) I need to establish the WCF proxy dynamically and cannot rely on some prebuilt proxy created by VS or the Silverlight tools. The clients in this case are mobile apps built with Xamarin.Forms.
The Code to create the "Channel":
public void Init(int timeout = 15)
{
ea = new EndpointAddress(string.Format("http://{0}:{1}/{2}", _settingsService.ConnectionIP, _settingsService.ConnectionPort, _settingsService.ConnectionEndpoint));
bhttpb = new BasicHttpBinding(BasicHttpSecurityMode.None);
bhttpb.SendTimeout = TimeSpan.FromSeconds(timeout);
cfIMMC = new ChannelFactory<IMaintMobileContract>(bhttpb, ea);
cfIMMC.Opened += cfIMMC_Opened;
cfIMMC.Faulted += cfIMMC_Faulted;
cfIMMC.Closed += cfIMMC_Closed;
immc = cfIMMC.CreateChannel(ea);
immc.Ping(); // This function is defined by me in the Contract. It only returns true, if the server can be reached.
}
So far everything works fine if the service is running, but the app has to run "offline" and then it gets weird.
When the connection is established there is no EndpointException or anything, and when a function is called it just sits there waiting until the timeout hits.
It would be really nice to get some information whether the WCF service is actually there or not. I have function calls that can take up to multiple minutes and it would be fatal for the app to wait that long when the WCF server is not there at all. How can I achieve that?
Update:
Right now it got even weirder. Now, aprox. 30 seconds after the Ping() fails, I get System.Net.Sockets.SocketException: Connection timed out and System.Net.WebException: Error: ConnectFailure (Connection timed out) out of nowhere.
Update 2 :
Here a pic of the CallStack:
If you need fast feedback regarding whether service is alive or not, then setup additional endpoint (with separate contract containing only Ping method) and set small timeouts for it.
And important part is to set send/receive timeouts to small value as well - this will ensure that Ping method returns/throws fast if service is not available.
As far as I remember WCF does not open channel (== does not connect to server) until you call one of the methods - that's why you don't have exceptions before Ping is called.
About exception after 30 seconds. Where do you see it? I mean is it Visual Studio that breaks there or do you have your application failing with unhandled exception? I'm asking it because I see this in the Xamarin/Mono code:
initConn = new WaitCallback (state => {
try {
InitConnection (state);
} catch {}
});
And it means that even though this exception is thrown after 30 seconds - it'll be swallowed. What really happens is that when request is sent (i.e. when you call Ping()) the runtime tries to open connection in background (your call stack confirms that) and 30 seconds is default Windows timeout for connection. WCF will fail earlier if it has lower timeout set (like in your case), but connection attempt will last for 30 seconds and will complete with exception.
So, my opinion is that you should not care about this exception, unless it somehow stops your application.
I'm learning about FaultException and CLR Exceptions in the context of WCF services but something is not clear.
In the book "Learning WCF" it says that when a service throws a normal CLR Exception it's caught by the service model, the service model constructs a SOAP message from that, sends it back to the client, and the exception is thrown at the client again. There the channel is faulted.
So I've built a service which throws a NullReferenceException.
A client calls the service, catches the exception and print the CommunicationState.
try
{
x = Proxy.Call(); // throws NullReferenceException at the service
}
catch (Exception ex) // or CommunicationException is the same
{
MessageBox.Show("" + Proxy.InnerChannel.State);
}
But the State member stays on Opened and I can call the service forever....
What is correct here? Should a client go into faulted state when a service throws a CLR exception and stays in Opened state when a service throws a FaultException? Or does it always stay open?
I can not find official confirmation, but here is what going on in my opinion:
You using BasicHttpBinding which does not keep connection open, but creates new one on every request. If you switch to NetTcpBinding, you will see expected behavior(just tested locally)
When error occures session's state gets in fault state and since binding such as basicHttpBinding does not support session at all you cannot distincly see that connection is in faulted state. Try to make use of binding which supports session such as netTcpBinding and you should discover that session, after exception being thrown, is not accessible.
I run .exe through windows service which reads the message from Private Queue. The service is all good and stable but at times the service stops (it actually does not stop, but it is not processing anything. Service status is still "Started", I need to manually restart it).
This one doesn't show up often but analyzing the memory dump of the .exe file, I found that so many threads encountered below exception.
Exception object: 0000000001436120
Exception type: System.Messaging.MessageQueueException
Message: External component has
thrown an exception.
System.Messaging.MessageQueueException- External component has thrown an exception
System.Messaging.MessageQueue.ReceiveCurrent(System.TimeSpan, Int32, System.Messaging.Interop.CursorHandle, System.Messaging.MessagePropertyFilter, System.Messaging.MessageQueueTransaction, System.Messaging.MessageQueueTransactionType)
System.Messaging.MessageQueue.Peek(System.TimeSpan)
Any idea why service encounters this exception?? Thanks in advance
I noticed that if you do a throw new InvalidCastException for example, the channel state on the client side is faulted. But if you throw new FaultException, the channel state on the client side is opened.
By curiosity, what is the reason why one faults the channel and the other doesn't?
The FaultException is a special case in WCF. It's meant to indicate that something happened on the service side that was an error, but at the same time, not fault the channel. This makes sense, given you can embed this information into the contract using the FaultContractAttribute to expose what can be expected from a contract.
Other exceptions are not really translatable in the WS world. Exceptions are a technology-specific abstraction, and each technology stack has a different representation of that abstraction (or in some cases, none at all).
That being said, when an exception that is not a fault exception is thrown on the server side, it is seen as catastrophic by the WCF runtime, and the channel must be faulted, as it is not known if you can proceed or not.
However, using FaultException, it implies you have some foresight into the conditions around why it was thrown and whether or not the underlying channel has been impacted or not.