Unexpected Error from Exception Handling Block in WCF for FaultExeption and FaultException<Tdetail>

Topics: Enterprise Library Core, Exception Handling Application Block, Logging Application Block
Aug 12, 2013 at 1:22 AM
Edited Aug 12, 2013 at 5:06 AM
Hi

I am getting an unexpected error from Enterprise Library Exception Handling Block v5 in WCF.

All I want to do is NotifyRethrow for FaultExeption and FaultException<Tdetail>, so client sees the FaultContract on their side

Please read further. Thanks in advance for any help.

I am working on a project where I had to use ExceptionShielding in WCF and not try-catch as we are logging all possible exceptions.

But there are cases where I just have to send information to the client in a Custom Data Fault Contract.

The following is a reproduction project of my actual solution:

Service Interface:
 [ServiceContract]
    public interface IService1
    {

        [OperationContract]
        [FaultContract(typeof(ServiceFaulty))]
        string GetData(int value);
    }

    [DataContract]
    public class ServiceFaulty
    {
        public Guid ErrorID { get; set; }
        public String Message { get; set; }
    }
Service Implementation:
 [ExceptionShielding("Policy")]
    public class Service1 : IService1
    {
        public string GetData(int value)
        {
            //Comment first line to trigger second behavior for testing 
            throw new Exception("Service Level Exception Ocured");
            throw new FaultException("Fault Exception Detected");
            return string.Format("You entered: {0}", value);
        }

    }
Following is my configuration:
<exceptionHandling>
    <exceptionPolicies>
      <add name="Policy">
        <exceptionTypes>
          <add name="FaultException" type="System.ServiceModel.FaultException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
            postHandlingAction="NotifyRethrow" />
          <add name="All Exceptions" type="System.Exception, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
            postHandlingAction="ThrowNewException">
            <exceptionHandlers>
              <add type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.WCF.FaultContractExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.WCF, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                exceptionMessage="Oops we goofed!" faultContractType="WcfService.ServiceFaulty, WcfService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
                name="Fault Contract Exception Handler">
                <mappings>
                  <add source="{Guid}" name="ErrorID" />
                </mappings>
              </add>
              <add name="Logging Exception Handler" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                logCategory="General" eventId="100" severity="Error" title="Enterprise Library Exception Handling"
                formatterType="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.TextExceptionFormatter, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling"
                priority="0" />
            </exceptionHandlers>
          </add>
        </exceptionTypes>
      </add>
    </exceptionPolicies>
  </exceptionHandling>
If you see I am trying to test two different behavior.
One for AllException where I want to Log all exceptions and throw a Custom Fault Contract.
The other I want to Bubble Up all the FaultException(s) to the Client Side raised by my code, so I am doing NotifyReThrow.

The first scenario is working fine but in the case I want to bubble up FaultContracts, I am getting the following error:
System.ServiceModel.FaultException: An error has occurred while consuming this service. Please contact your administrator for more information. Error ID: 7e1271c6-c198-428e-aa4f-89c00a194a36

Server stack trace: 
   at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
Also, I am getting the same error If Itry to throw any FaultException<TDetail> object from my service.

The Exception shielding deletes the FaultContract, throws a FaultException object for client and gives me the same Contact your administrator with a Random Guid error as showed above. All I want to do is NotifyRethrow for FaultExeption and FaultException<Tdetail>, so client sees the FaultContract on their side
Aug 12, 2013 at 6:10 PM
If you change from NotifyRethrow to ThrowNewException it should work:
 <add name="FaultException" type="System.ServiceModel.FaultException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
            postHandlingAction="ThrowNewException" />

Some other notes: ServiceFaulty properties should be annotated with the DataMember attribute (if you want to send them over the wire). If you want to log the exception information then you should move the Logging Exception Handler before the Fault Contract Exception Handler. Also, if you want a FaultException<T> to be propagated to the caller then it should be explicitly added to the interface. E.g.:
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        [FaultContract(typeof(ServiceFaulty))]
        [FaultContract(typeof(PassThroughValidationFault))]
        string GetData(int value);
    }

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Aug 12, 2013 at 9:33 PM
Edited Aug 12, 2013 at 9:33 PM
Thanks Randy.

It worked. The point was to ThrowNewException insted of None or NotifyRethrow.

Also, you would like to review the FAQ question in the same context:

https://entlib.codeplex.com/wikipage?title=How%20do%20I%20make%20the%20Exception%20Handling%20Application%20Block%20ExceptionShielding%20attribute%20not%20shield%20FaultExceptions%3f
It is the third FAQ Question but it says do None as the Action.

Also the MSDN site says to propagate an exception do a NotifyRethrow:
http://msdn.microsoft.com/en-us/library/ff650615.aspx

Check the Solution Section in the above link.

It says "Configure the relevant exception type to use NotifyRethrow as its PostHandlingAction.".

Do not know what that is about?

Anyway, thanks man. I appreciate it. You rule!
Aug 13, 2013 at 1:11 AM
I believe the discrepancy in behavior is a result of some arcane behavior. If you use the policy name "WCF Exception Shielding" (which is the default name) then the other postHandlingActions work as described.

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Aug 23, 2013 at 6:40 PM
Edited Aug 23, 2013 at 6:45 PM
Hi Randy

One more thing. I am using Enterprise Library Version 5.0.414 and as I add a Longging Handler to the above configuration. i.e. Log and Throw Fault, I am getting the same kind of error as above i.e.
System.ServiceModel.FaultException: An error has occurred while consuming this service. Please contact your administrator for more information. Error ID: 7e1271c6-c198-428e-aa4f-89c00a194a36

Server stack trace: 
   at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
But I tested it in version 5.0.505. It works fine.

Following is my configuration:
  <loggingConfiguration name="" tracingEnabled="true" defaultCategory="General">
    <listeners>
      <add name="Flat File Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        fileName="trace.log" formatter="Text Formatter" />
    </listeners>
    <formatters>
      <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        template="Timestamp: {timestamp}{newline}&#xA;Message: {message}{newline}&#xA;Category: {category}{newline}&#xA;Priority: {priority}{newline}&#xA;EventId: {eventid}{newline}&#xA;Severity: {severity}{newline}&#xA;Title:{title}{newline}&#xA;Machine: {localMachine}{newline}&#xA;App Domain: {localAppDomain}{newline}&#xA;ProcessId: {localProcessId}{newline}&#xA;Process Name: {localProcessName}{newline}&#xA;Thread Name: {threadName}{newline}&#xA;Win32 ThreadId:{win32ThreadId}{newline}&#xA;Extended Properties: {dictionary({key} - {value}{newline})}"
        name="Text Formatter" />
    </formatters>
    <categorySources>
      <add switchValue="All" name="General">
        <listeners>
          <add name="Flat File Trace Listener" />
         
        </listeners>
      </add>
    </categorySources>
    <specialSources>
      <allEvents switchValue="All" name="All Events" />
      <notProcessed switchValue="All" name="Unprocessed Category" />
      <errors switchValue="All" name="Logging Errors &amp; Warnings">
        <listeners>
          <add name="Flat File Trace Listener" />
        </listeners>
      </errors>
    </specialSources>
  </loggingConfiguration>
  <exceptionHandling>
    <exceptionPolicies>
      <add name="ABCDExceptionPolicy">
        <exceptionTypes>
          <add name="FaultException`1" type="System.ServiceModel.FaultException`1[[MyProject.ABCD.Services.DataContract.ABCDValidationException, MyProject.ABCD.Services.DataContract, Version=1.0.0.0, Culture=neutral, PublicKeyToken=499e076136873346]], System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
            postHandlingAction="ThrowNewException" />
          <add name="FaultException`1 2" type="System.ServiceModel.FaultException`1[[MyProject.ABCD.Services.DataContract.ABCDBusinessException, MyProject.ABCD.Services.DataContract, Version=1.0.0.0, Culture=neutral, PublicKeyToken=499e076136873346]], System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
            postHandlingAction="ThrowNewException" />
          <add name="FaultException" type="System.ServiceModel.FaultException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
            postHandlingAction="ThrowNewException" />
          <add name="All Exceptions" type="System.Exception, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
            postHandlingAction="ThrowNewException">
            <exceptionHandlers>
              <add type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.WCF.FaultContractExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.WCF, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                faultContractType="MyProject.ABCD.Services.DataContract.ABCDServiceFault, MyProject.ABCD.Services.DataContract, Version=1.0.0.0, Culture=neutral, PublicKeyToken=499e076136873346"
                name="Fault Contract Exception Handler">
                <mappings>
                  <add source="{Guid}" name="ErrorID" />
                </mappings>
              </add>
            </exceptionHandlers>
          </add>
        </exceptionTypes>
      </add>
    </exceptionPolicies>
  </exceptionHandling>
I am limited to use 5.0.414 version of Enterprise Library. Can you suggest where is the error. As usual, your help is deeply appreciated.

Thanks
Gaurav
Aug 23, 2013 at 6:51 PM
Edited Aug 23, 2013 at 6:53 PM
Quick thought: one of the most common issues in 5.0.414.0 (that was fixed in 505) was FileConfigurationSource using a relative path. Just curious if that applies to you?

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to