I know that we can use FaultException and FaultContract to catch these exception?
Is there any other way to (Except FaultException/FaultContract) catch specifically these two Exception (Transport and Communication)?
According to the Microsoft documentation, transport and communication errors are handled by the CommunicationException class.
Communication errors occur when a network is unavailable, a client
uses an incorrect address, or the service host is not listening for
incoming messages. Errors of this type are returned to the client as
CommunicationException or CommunicationException-derived classes.
The following provides a good overview of the three categories of WCF errors:
Communication Errors
Proxy/Channel Errors
Application Errors
https://learn.microsoft.com/en-us/dotnet/framework/wcf/wcf-error-handling
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.
In my application, while logging exceptions, I need to show user friendly and localized error messages to the clients.
ie: CustomerNotFoundException should display the following to end user.
Customer-001
Customer was not found
I hope it is clear so far. I have services for i18n and error messages.
My error messages microservis provides key value pairs of Language, ErrorId and Error Message:
ie:
Error: Customer -001; Message: Customer Not found; Language:en-US
My question is about designing this process:
Should I convert exceptions to error messages that can be displayed to clients in a middleware? if so how do i map exceptions to error messages?
Or Should I inject ErrorService or I18N service in to the exceptions to provide message etc to the client ?
or is there a better way?
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 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.
I want to catch all unhandled exceptions thrown in a remote object on the server and log them there before I translate them into some custom exception so that specific exceptions do not cross the client/server boundary.
I think I have to use a custom channel sync, but can anyone confirm this and/or have any other advice to give?
I would use the Microsoft Enterprise Library Exception Handling app block -- it lets you handle errors and convert specific types of exception to a different type of exception before rethrowing to the client.
After finding Eliyahu Baker's helpful blog post and reading chapter 12 of Rammer's Advanced .NET Remoting I wrote a custom channel sink that does what I want. This intercepts any exception and logs it locally before sending it on to the client.
Ideally, I'd like to log the exception and raise a more generic one for the client, but I haven't cracked that nut yet.