WCF FaultException

15,172

Solution 1

For simplifying the approach of throwing a FaultException from the service and catching and processing it at the client side kindly follow this code:

Service:

public bool UpdateSpotCheckInventory(SpotCheck transferObject)
{
    bool blnUpdated = false;
    try
    {
        blnUpdated = SpotCheckCollectionGateway.UpdateData(transferObject);
        LogMessage.WriteEventLog("SpotCheck records updated successfully", "Ryder.ShopProcessService.SOA", 3, null);
        return blnUpdated;
    }
    catch (Exception ex)
    {
        //throw fault exception here on service
        throw new FaultException("A fatal exception occurred while processing your request", new FaultCode("1000"))
    }
}

Client:

catch (FaultException ex)
{
    ex.Detail.ApplicationID = "ShopProcessService";
    ex.Detail.LogEventType = LogEventTypeEnum.Error;
    serviceClient.Abort();

    // You can also access the custom message and error code sent from the service...
    String customErrorCode = ex.Code.Name;
    String customErrorMessage = ex.Reason;
}

I'm sure this would solve your problems. :-)

Solution 2

Please try define the CustomFault(MathFault in this example) as a data contract rather than Operation Contract, like:

[DataContract]
public class MathFault
{    
    //...
}

At the client side:

static void Main(string[] args)
{
    ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
    try
    {
        int value1 = 22;
        int value2 = 0;
        int result = client.Divide(value1, value2);
        Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);
        client.Close();
    }
    catch (FaultException<MathFault> e)
    {
        Console.WriteLine("FaultException<MathFault>: Math fault while doing " + e.Detail.Operation + ". Problem: " + e.Detail.ProblemType);
        client.Abort();
        Console.ReadLine();
    }
}

See more: Fault Contract

Share:
15,172
sagesky36
Author by

sagesky36

Updated on June 04, 2022

Comments

  • sagesky36
    sagesky36 almost 2 years

    When building a WCF service, if I don't include my contract for the FaultException in the service, I'm able to create a WCF service reference on the client with all of the members included in the Reference.cs file.

    If I include my FaultException contract, two things happen.

    1. In the WCF test client, I have a red "X" next to the contract name (CreateFaultMessage)

    2. When I create the WCF service reference, not all of the members are included in the Reference.cs file.

    I am hoping somebody will be able to inform me what I'm doing incorrectly as far as creating my FaultException contract since I am not a WCF expert.

    Below, is the code declaration of my contract in the interface.

    [OperationContract]
            [FaultContractAttribute(typeof(LogEventArgs), ProtectionLevel = ProtectionLevel.None)]
            Exception CreateFaultMessage(Exception ex, string method);
    

    Below, are methods in the class which implement the interface. Notice the call to the CreateFaultMessage method in the catch block of the PostTransmissionRecord method.

    public bool PostTransmissionRecord(TransmissionRecord transmissionRecord)
    {
        bool blnUpdated = false;
    
        try
        {
            blnUpdated = TransmissionRecordGateway.InsertData(transmissionRecord);
            LogMessage.WriteEventLog("Transmission records updated successfully", "Ryder.ShopProcessService.SOA", 3, null);
    
            return blnUpdated;
        }
        catch (Exception ex)
        {
            LogMessage.WriteEventLog("Class: ShopProcessService" + CrLf + "Method: PostTransmissionRecord" + CrLf + "Error: " + ex.Message + CrLf + "InnerException: " + ex.InnerException + CrLf + "Source: " + ex.Source + CrLf + "StackTrace: " + ex.StackTrace, "Ryder.ShopProcessService.SOA", 1, null);
            IssueRemedyTicket("Class: ShopProcessService" + CrLf + "Method: PostTransmissionRecord" + CrLf + "Error: " + ex.Message + CrLf + "InnerException: " + ex.InnerException + CrLf + "Source: " + ex.Source + CrLf + "StackTrace: " + ex.StackTrace);
            CreateFaultMessage(ex, "UpdateSearchInventory");
            return blnUpdated;
        }
    }
    
    public Exception CreateFaultMessage(Exception ex, string method)
    {
        LogEventArgs detail = new LogEventArgs();
    
        detail.ApplicationID = "ShopProcessService";
        detail.ExceptionMessage = ex.Message;
        detail.LogEventType = LogEventTypeEnum.Error;
        detail.Method = method;
        detail.Source = ex.Source;
        detail.StackTrace = ex.StackTrace;
        if (ex.InnerException != null)
            detail.InnerExceptionMessage = ex.InnerException.ToString();
        else
            detail.InnerExceptionMessage = null;
    
        throw new FaultException<LogEventArgs>(detail);
    }
    

    UPDATED CODE

    DataContract class

    namespace Ryder.Enterprise.DataTransferObjects
    {
        [Serializable, DataContract(Name = "LogEventArgs", Namespace = "http://www.Ryder.com/SOA/DataContracts/2014/02/17")]
        public class LogEventArgs
        {
            private string applicationID;
            private string method;
            private LogEventTypeEnum logEventType;
            private string exceptionMessage;
            private string innerExceptionMessage;
            private string stackTrace;
            private string source;
    
            [DataMember(Name = "ApplicationID")]
            public string ApplicationID
            {
                get
                {
                    return applicationID;
                }
                set
                {
                    applicationID = value;
                }
            }
    .
    .
    .
    

    Service method throwing FAULTEXCEPTION

    public bool UpdateSpotCheckInventory(SpotCheck transferObject)
            {
                bool blnUpdated = false;
    
                try
                {
                    blnUpdated = SpotCheckCollectionGateway.UpdateData(transferObject);
                    LogMessage.WriteEventLog("SpotCheck records updated successfully", "Ryder.ShopProcessService.SOA", 3, null);
    
                    return blnUpdated;
                }
                catch (Exception ex)
                {
                    //throw fault exception here on service
                    return blnUpdated;
                }
            }
    

    CLIENT CODE CATCHING THE FAULTEXCEPTION

    catch (FaultException<LogEventArgs> ex)
                {                   ex.Detail.ApplicationID = "ShopProcessService";
                    ex.Detail.LogEventType = LogEventTypeEnum.Error;
                    serviceClient.Abort();
                } 
    
  • sagesky36
    sagesky36 about 10 years
    Referring to the Updated Code. This question is for the DataContract class: Haixia, I very much appreciate your help :) I modified my code, but am unsure how to throw the FaultException. I have the following set up now on my service now: I'm referencing a class that contains the DataContract as partially seen below. I think I would only need the applicationID and logeventType as the FaultException would seem to carry over the other properties I have listed. Please let me know if that is true.
  • sagesky36
    sagesky36 about 10 years
    This question is for the Service method throwing the FAULT exception. This is the method where I want to throw the FaultException. Syntactically, how would that look? Not sure how to place it in the Catch block or if even the Catch block is correct.
  • sagesky36
    sagesky36 about 10 years
    This question pertains to the CLIENT CODE CATCHING THE FAULTEXCEPTION. This is what I have on my client now. When the FaultException gets hit, it is transmitted back to the calling service and they would receive the exception message with the appropriate properties including the ex.Message, stacktrace, method, etc?
  • sagesky36
    sagesky36 about 10 years
    Finally, the last question: what would a Catch block look like on the receing end of getting the FaultException back from a service?
  • dhrumilap
    dhrumilap about 10 years
    Check my new answer where I've shown how to throw a FaultException with custom message and error code in the service and how to handle it in the client.
  • sagesky36
    sagesky36 about 10 years
    Haixia, thanks for the update. I understand. One last question... If I include properties in the LogEventArgs class, can I or do I need to place the following code before aborting the client? ex.Detail.ApplicationID = "ShopProcessService"; ex.Detail.LogEventType = LogEventTypeEnum.Error; ex.Detail.FaultCode = ex.Code; ex.Detail.Reason = ex.Reason; ex.Detail.ExceptionMessage = ex.Message; or would the ExceptionMessage, etc, be redundant?