Exception handling – WCF perspective
WCF service is a programming paradigm that offers a common platform for writing service contracts using Microsoft provided CLR environment where heterogeneous platforms/clients technology may consume these contracts. So propagation of exception details occurred in service to the client applications must happen in a platform-agnostic manner so that a client application can also get to know exactly what went wrong in the service.
FaultException is the exception class defined in System.ServiceModel and inherits CommunicationException class. In general it represents a SOAP fault. The constructor accepts two main arguments (reason which is a string and a FaultCode object). In the example below we are making use of this class.
The concern in this approach is that while writing the exception handling routine; the developer has to think of every possible exception that can result from the underlying code. Otherwise a catch-all exception (as shown above after the highlighted block) can be written. But in that case also very limited information on how the exception occurred can be made available to the client application.
A better way – strongly typed Faults
We can define our Fault contracts (just like Data contracts) that will contain more relevant information about the source and reason for the SOAP faults (as shown below).
In the client side we will need to catch the exception as shown below:
Important Note: During development phase; “includeExceptionDetailInFaults” must be set to true so that the service method can return the fault details to the client application (as shown in the following image) Otherwise a generic exception description is returned.
This attribute can also be changed from individual service implementation using ServiceBehavior attribute as shown below.
Important Note: This option has been provided mainly for the ease of debugging purpose during development phase. It is strongly discouraged to put this setting on while releasing a service in production as it can expose severe security risks.
An introduction to transaction handling in WCF service
Handling of transaction contains the same flavor of ACID property in WCF world as with any other programming constructs. Here we need to take some crucial decision as to which mode of transaction our service needs to implement:
Option 1: Service side only – in this case transaction has to be within the scope of the service method only and it is not needed to propagate to the client.
Option 2: Client side only – in this case transaction has to be implemented only within the client method and service does not need to participate in it.
Option 3: Client/Service both – this option is used when transaction is initiated either in service or in client side but it is needed to be propagated to the other in order to commit the whole operation.
The fulcrum of transaction control lies with a binding configuration item called “TransactionFlow”. One more point to be noted that this option is available only with the following bindings – NetTcpBinding, NetNamedPipeBinding, wsHttpBinding (we will use this as shown in Pic 6), wsDualHttpBinding and wsFederationHttpBinding.
Next step is to make the operation contract transaction aware as shown in following figure:
An operation contract can have three different types of values in TransactionFlow:
- Allowed – this is the case where transaction may be flowed from client to service or vice versa; this corresponds to the option 3 transaction mode mentioned above (the service will try to use a transaction scope from client call and if it is not there the scope will get created).
- Mandatory – this option is used when transactional flow must exists between service and client method consuming the service; this corresponds to option 2 (service will always expect a transaction scope to be flown from client method).
- NotAllowed – this is the default option where transaction flow does not exist between service method and client method. This corresponds to option 1 (in this case service will create its own transaction scope whether the client has its separate scope created or not).
Next important thing is to make the operation behavior act according to the transaction methodology. We need to specify TransactionScopeRequired property of OperationBehavior to true in order to make it transaction aware as shown in the following image:
Now, as we have mentioned in OperationContract stage that TransactionFlowOption is allowed; so we are using the scope in client method call (as shown in following image).
Here, TransactionScope is a class in System.Transactions namespace.
To summarize, Appropriate exception handling using FaultContract and implementing robust transaction implementation ensures proper flowing of data from client method to service method and vice versa.