none
TransactionAbortedException hides the WCF Fault? RRS feed

  • Question

  • I have the following scenario :

    A WCF Client starts and propagates a transaction to a WCF Service using a TransactionScope.

    The client contract is the following :

    public interface IMyService
    {
        [OperationContract]
        [FaultContract(typeof(MyException))]
        [TransactionFlow(TransactionFlowOption.Mandatory)]
        bool DoSomeTransactionalWork();
    
        [OperationContract]
        [FaultContract(typeof(MyException))]
        bool DoSomeWork();
    
    }

    The proxy used is not generated, it is based on the well known wrapper :

    using (TransactionScope ts = new TransactionScope())
    {
        Service<IMyService>.Use(proxy =>
        {
            proxy.DoSomeTransactionalWork();
        });
    }

    The WCF Service method, which requires a transaction in the contract definition and votes implicitly for it, throws a FaultException<MyException>.

    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    public bool DoSomeTransactionalWork()
    {
        throw new FaultException<MyException>(new MyException(myMessage));
    }    

    The WCF proxy receives a TransactionAbortedException with InnerException set to null therefore losing the WCF Fault.

    try
    {
        using (TransactionScope ts = new TransactionScope())
        {
            Service<IMyService>.Use(proxy =>
            {
                proxy.DoSomeTransactionalWork();
            });
        }
    }
    catch (TransactionAbortedException tae)   
    {
        // tae.InnerException is null
    }

    In a similar scenario where a Transaction isn't required by the contract for a service method :

    public bool DoSomeWork()
    {
        throw new FaultException<MyException>(new MyException(myMessage));
    }  

    and the client simply calls it via the same proxy code, a FaultException<MyException> is received.

    try
    {
            Service<MyService>.Use(proxy =>
            {
                proxy.DoSomeWork();
            });
    
    }
    catch (FaultException<MyException> tae)   
    {
        //
    }

    Am I missing something or is it the expected behavior ?

    TIA.


    • Edited by O. MATROT Monday, June 24, 2013 12:53 PM
    Monday, June 24, 2013 12:52 PM

Answers

  • If an operation is declared with a custom type of fault exception and the same is thrown from the server, then indeed we can catch the exception inside the catch block and can see the properties of fault class, by doing "ex.Details.Property1", rather than relying on the inner exception property of base class.

    Server:
    throw new FaultException<MyException>(new MyException("We got error: "));

    Client:
    catch (FaultException<MyException> ex)
    {
                    Console.WriteLine("Message: " + ex.Detail.Property1);
    }

     

    Now for the second scenario when you have the method decorated with the Transaction related attributes, make sure what type of exceptions are we talking about

    Case 1:
    Unhandled exception.

    Case 2:
    Handled exception.


    Prefer to use a try catch block on server side and convert the unhandled exception into the custom exception object only.
    If you don't do that than the exception is thrown to client as Fault Exception <TDetail>, value can be retrieved if the "IncludeExceptionDetailsInFaults = true"


    However you can only catch this unhandled exception in either the CommunicationException or Exception class at client side.

     

    In you description you mentioned that when you throw the Fault exception from server you are ending up in "TransactionAbortedException " catch block.
    Which should actually not happen, since even if this exception is thrown from server side, it will get converted to FaultException<TDetail> object and then would be give to client (it would not come as "TransactionAbortedException").
    For the method decorated with the custom Fault Exception object, it becomes easier to send this Fault objects on channel to client.

    These are valid for all those exception which are not fatal and don't result in server shutting down.

     

    Some References
    ==================
    http://msdn.microsoft.com/en-us/library/ms733721.aspx

    "It is strongly recommended that service operations declare their faults by using the FaultContractAttribute attribute to formally specify all SOAP faults that a client can expect to receive in the normal course of an operation. It is also recommended that you return in a SOAP fault only the information that a client must know to minimize information disclosure. "


    Undeclared SOAP Faults and Debugging:

    Declared SOAP faults are extremely useful for building robust, interoperable, distributed applications. However, in some cases it is useful for a service (or duplex client) to send an undeclared SOAP fault, one that is not mentioned in the Web Services Description Language (WSDL) for that operation. For example, when developing a service, unexpected situations can occur in which it is useful for debugging purposes to send information back to the client. In addition, you can set the System.ServiceModel.ServiceBehaviorAttribute.IncludeExceptionDetailInFaults property or the System.ServiceModel.Description.ServiceDebugBehavior.IncludeExceptionDetailInFaults property to true to permit WCF clients to obtain information about internal service operation exceptions. Both sending individual faults and setting the debugging behavior properties are described in Sending and Receiving Faults.

     

    http://msdn.microsoft.com/en-us/library/ms732013.aspx
    Sending Undeclared Faults:

    "Sending undeclared faults can be very useful to quickly diagnose and debug problems in WCF applications, but its usefulness as a debugging tool is limited. More generally, when debugging it is recommended that you use the System.ServiceModel.Description.ServiceDebugBehavior.IncludeExceptionDetailInFaults property. When you set this value to true, clients experience such faults as FaultException exceptions of type ExceptionDetail"


    "If you declare a SOAP fault of type string, and then throw this in your service as a FaultException where the type parameter is a System.String the string value is assigned to the System.ServiceModel.FaultException.Detail property, and is not available from System.ServiceModel.FaultException.ToString."


    Hope his help ...


    For more specific help, please engage us via paid support incident ticket.

    • Marked as answer by O. MATROT Wednesday, July 24, 2013 8:41 AM
    Tuesday, July 16, 2013 3:02 PM

All replies

  • If an operation is declared with a custom type of fault exception and the same is thrown from the server, then indeed we can catch the exception inside the catch block and can see the properties of fault class, by doing "ex.Details.Property1", rather than relying on the inner exception property of base class.

    Server:
    throw new FaultException<MyException>(new MyException("We got error: "));

    Client:
    catch (FaultException<MyException> ex)
    {
                    Console.WriteLine("Message: " + ex.Detail.Property1);
    }

     

    Now for the second scenario when you have the method decorated with the Transaction related attributes, make sure what type of exceptions are we talking about

    Case 1:
    Unhandled exception.

    Case 2:
    Handled exception.


    Prefer to use a try catch block on server side and convert the unhandled exception into the custom exception object only.
    If you don't do that than the exception is thrown to client as Fault Exception <TDetail>, value can be retrieved if the "IncludeExceptionDetailsInFaults = true"


    However you can only catch this unhandled exception in either the CommunicationException or Exception class at client side.

     

    In you description you mentioned that when you throw the Fault exception from server you are ending up in "TransactionAbortedException " catch block.
    Which should actually not happen, since even if this exception is thrown from server side, it will get converted to FaultException<TDetail> object and then would be give to client (it would not come as "TransactionAbortedException").
    For the method decorated with the custom Fault Exception object, it becomes easier to send this Fault objects on channel to client.

    These are valid for all those exception which are not fatal and don't result in server shutting down.

     

    Some References
    ==================
    http://msdn.microsoft.com/en-us/library/ms733721.aspx

    "It is strongly recommended that service operations declare their faults by using the FaultContractAttribute attribute to formally specify all SOAP faults that a client can expect to receive in the normal course of an operation. It is also recommended that you return in a SOAP fault only the information that a client must know to minimize information disclosure. "


    Undeclared SOAP Faults and Debugging:

    Declared SOAP faults are extremely useful for building robust, interoperable, distributed applications. However, in some cases it is useful for a service (or duplex client) to send an undeclared SOAP fault, one that is not mentioned in the Web Services Description Language (WSDL) for that operation. For example, when developing a service, unexpected situations can occur in which it is useful for debugging purposes to send information back to the client. In addition, you can set the System.ServiceModel.ServiceBehaviorAttribute.IncludeExceptionDetailInFaults property or the System.ServiceModel.Description.ServiceDebugBehavior.IncludeExceptionDetailInFaults property to true to permit WCF clients to obtain information about internal service operation exceptions. Both sending individual faults and setting the debugging behavior properties are described in Sending and Receiving Faults.

     

    http://msdn.microsoft.com/en-us/library/ms732013.aspx
    Sending Undeclared Faults:

    "Sending undeclared faults can be very useful to quickly diagnose and debug problems in WCF applications, but its usefulness as a debugging tool is limited. More generally, when debugging it is recommended that you use the System.ServiceModel.Description.ServiceDebugBehavior.IncludeExceptionDetailInFaults property. When you set this value to true, clients experience such faults as FaultException exceptions of type ExceptionDetail"


    "If you declare a SOAP fault of type string, and then throw this in your service as a FaultException where the type parameter is a System.String the string value is assigned to the System.ServiceModel.FaultException.Detail property, and is not available from System.ServiceModel.FaultException.ToString."


    Hope his help ...


    For more specific help, please engage us via paid support incident ticket.

    • Marked as answer by O. MATROT Wednesday, July 24, 2013 8:41 AM
    Tuesday, July 16, 2013 3:02 PM
  • You're right, this is working fine with a synchronous call, I receive my custom Fault on client side.

    My problem was that, when making an asynchronous (APM) call to the service, I was not checking the state of the transaction before calling EndDoSomeTransactionalWork. I was inccrrectly trying to create a DependentTransaction from the aborted transaction, leading to the TransactionAbortedException.

    Wednesday, July 24, 2013 8:41 AM