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.
Related
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
Looking at the Service Remoting article, I can see the following:
If Transient Exceptions occurs, proxy retries the call.
What specifically is considered a "Transient Exception" by the proxy?
In the past we've handled Timeout, InvalidOperation (See here), FabricNotReadableException (See here) and FabricTransientExceptions ourselves for operations on Reliable Collections - Should we be doing the same for our interactions with other Services using SF Remoting?
As an example:
//Get Proxy
var serviceProxy = ServiceProxy.Create<IService>(GetServiceUri(), GetPartitionKey());
//Make Call to method which has no internal handling for transient SF failures...
//Should this be wrapped with a retry policy?
var result = await serviceProxy.GetAll();
As per the exception handler for remoting (ServiceRemotingExceptionHandler.cs), it appears that the Proxy will handle the following errors:
FabricNotPrimaryException when the Primary has moved
FabricTransientException exceptions
FabricNotReadableException exceptions
You may still wish to handle Timeout exceptions yourself.
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 want to know what are the cases in which WCF proxy (generated by vs2008 or svcutil) becomes faulted (fault state)? so I can recreate new instance and avoid use the faulted one.
currently I am handling TimeoutException,FaultException,CommunicationObjectAbortedException
try
{
client.Method1(args);
}
catch (TimeoutException)
{
client.Abort();
ReCreate();
}
catch (FaultException)
{
client.Abort();
ReCreate();
}
catch (CommunicationObjectAbortedException)
{
client.Abort();
ReCreate();
}
I think I can avoid all these types and handle only the parent CommunicationException, is this sufficient? I need comments
Any uncaught exception on the server side that isn't handled and converted into a FaultException or FaultException<T> will likely fault your channel. In a per-call scenario or a one-way scenario, you often don't really care about the channel being faulted, but in a session-based scenario, you definitely will!
Your best bet is to really try and catch all exceptions on the server side and either just suppress them (log them on the server and don't do anything), or return them to the client in a FaultException way.
In order to do that, your service implementation should also implement the IErrorHandler interface which allows you to do just that - catch all exceptions and either logging+suppressing them, or converting them to SOAP faults.
Marc
WCF proxy object can become faulted because of any sort of exception except a faultException. So basically you best bet is just to check the proxy state and of it is faulted create a new one.
Another thing to keep in mind is that faulted is related to WCF sessions. If you don't need WCF sessions make sure to turn them off and you have prevented a whole series of possible issues.
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.