0

I would like to Include a User Define Exception in FaultContract of WCF. In my WCF application, I would like to encapsulate Exception instance/UserDefine Exception Instance in FaultContract. Please Find my below UserDefine Exception.

public class UserExceptions : Exception
{
    public string customMessage { get; set; }

    public string Result { get; set; }

    public UserExceptions(Exception ex):base(ex.Message,ex.InnerException)
    {

    }
}

public class RecordNotFoundException : UserExceptions
{
    public RecordNotFoundException(Exception ex): base(ex)
    {

    }
}

public class StoredProcNotFoundException : UserExceptions
{
    public string innerExp { get; set; }

    public StoredProcNotFoundException(Exception ex,string innerExp)
        : base(ex)
    {
        this.innerExp = innerExp;
    }
}

[DataContract]
public class ExceptionFault
{ 
    [DataMember]
    public UserExceptions Exception { get; set; }

    public ExceptionFault(UserExceptions ex)
    {
        this.Exception = ex;
    }
}

And I am throw Exception in service as below

try
        {
            //Some Code
            //Coding Section 
                    throw new RecordNotFoundException(new Exception("Record Not Found"));
            //Coding Section
        }
        catch (RecordNotFoundException rex)
        {
            ExceptionFault ef = new ExceptionFault(rex);
            throw new FaultException<ExceptionFault>(ef,new FaultReason(rex.Message));
        }
        catch (Exception ex)
        {
            throw new FaultException<ExceptionFault>(new ExceptionFault((UserExceptions)ex),new FaultReason(ex.Message));
        }

try block catch CustomException(RecordNotFoundException) but it is not able to send that exception to client.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Sourabh
  • 86
  • 1
  • 7

1 Answers1

0

You need to add the FaultContract attribute to your OperationContract methods so that the SOAP client knows to expect the exception type

[OperationContract]
[FaultContract(typeof(MathFault))]
int Divide(int n1, int n2);

Your catch block needs to catch FaultException<T>

catch (FaultException<MathFault> e)
{
    Console.WriteLine("FaultException<MathFault>: Math fault while doing " + e.Detail.operation + ". Problem: " + e.Detail.problemType);
    client.Abort();
}

Its best to have a DataContract for each exception type, rather than trying to wrap them all up into one DataContract

[DataContract]
public class MathFault
{    
    private string operation;
    private string problemType;

    [DataMember]
    public string Operation
    {
        get { return operation; }
        set { operation = value; }
    }

    [DataMember]        
    public string ProblemType
    {
        get { return problemType; }
        set { problemType = value; }
    }
}

If you want to include implementations of UserExceptions in your DataContract then you may need to use the KnownType attribute so that the SOAP client is aware of the types:

[DataContract]
[KnownType(typeof(RecordNotFoundException))]
[KnownType(typeof(StoredProcNotFoundException))]
public class ExceptionFault
{ 
    [DataMember]
    public UserExceptions Exception { get; set; }

    public ExceptionFault(UserExceptions ex)
    {
        this.Exception = ex;
    }
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Glen Thomas
  • 10,190
  • 5
  • 33
  • 65
  • Thanks Glen for your quick response, however I would like to include original Exception in my FaultContract(MathFault in your example), So that client will be able to to get actual exception and other custom data like Operation and Problem. – Sourabh Apr 07 '16 at 16:13
  • In Short, I would like to serialize actual Exception and sent that to client through wire. – Sourabh Apr 07 '16 at 16:14
  • @Sourabh Ah I see. With a SOAP service you can only transmit custom types that the client is aware of through a DataContract. Adding the KnownType attribute might help with this. – Glen Thomas Apr 07 '16 at 16:18
  • Why I can't I inherit Exception class and mark it as [DataContract] ? It says Extended class can not be serialize. – Sourabh Apr 07 '16 at 16:21
  • System.Runtime.Serialization.InvalidDataContractException: Type 'WcfSampleService.UserExceptions' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types. – Sourabh Apr 07 '16 at 16:38
  • @Sourabh Can you make your exception classes data contracts? – Glen Thomas Apr 08 '16 at 09:39
  • Nope, when I am trying to provide [datacontract] attribute to my class which is extended from Exception, it throws runtime an error saying Extended exception class can not be ISerializable. .. – Sourabh Apr 10 '16 at 08:21
  • @Sourabh Then I would suggest just using a DataContract instead and taking the data from the exception that you will need on the client. – Glen Thomas Apr 10 '16 at 10:55
  • Agree with you, Thanks!! – Sourabh Apr 13 '16 at 09:46
  • 2
    @Sourabh If you add the [Serializable] attribute to your exception instead of the [DataContract] it will fix this issue. The serializable attribute is not inherited from the base Exception class. You will also need to create a constructor UserExceptions(SerializationInfo info, StreamingContext context): base(info, context) for deserialization – Mallek Sep 13 '16 at 01:04
  • Use [Serializable] to replace [DataContract] works for me. Please remember to remove the [DataMember] for the properties. – Feng May 27 '21 at 05:31