In this article, we are going to see, how to use the Fault contracts in WCF programming.
What is WCF?
WCF (Windows Communication Foundation) is a .NET dedicated communication framework. WCF provides an easy way to expose our methods as services and consuming the existing services as traditional methods. (More about the WCF can be found in my previous article: WCF Programming for Beginners.)
What are SOAP Faults?
In all managed applications we use the Exception objects to handle the errors. Similarly in WCF programming also to handle the errors and convey that error information from service to client and client to service we use the SOAP faults. FaultContractAttribute, which is defined in the namespace: System.ServiceModel.FaultContractAttribute, is used to declare customized SOAP faults.
SOAP Faults mainly of two types:
- Declared SOAP faults. - These are the SOAP faults that are specified on the operations by using the FaultContractAttribute.
- Undeclared SOAP faults. - These are SOAP faults that occurs in the operations but are not specified on the operations by using the FaultContractAttribute.
- [AttributeUsageAttribute(AttributeTargets.Method, AllowMultiple = true, Inherited = false)]
- public sealed class FaultContractAttribute : Attribute
Listing 1: Fault Contract Attribute Syntax
Creating Customized SOAP Faults
To create the customized SOAP faults:
- Declare and define the structure for our customized SOAP fault.
- Attach the customized SOAP fault to the operations by using the FaultContractAttribute.
- Check for the error condition and raise the Customized SOAP fault in service operations.
- Handle the SOAP faults at the client side.
Here I am going to explain all the above steps by using a sample WCF Service.
Sample Program:
Let us take a WCF service, which has a small function "GetEmpDetails (string EmpID) ". This function accepts empid as input parameter and check for that employee record against the DB. If the employee record exists then it returns that record, if not then it should through a custom fault message to the client, saying that "Employee Record does not exist".
- String GetEmpDetails( string EMPID)
- {
- // Check For the "EMPID" record in DataBase.
- //On Success return the emp details to the client.
- //On Failure return the Custom SOAP Fault message to the client.
- }
In this sample program we are going to create custom SOAP Fault that contains an error message string property.
In WCF we have to use the DataContractAttribute, DataMemberAttribute to expose the properties /variable/ events /indexes from WCF service to clients.
- /// <summary>
- /// This is structure is used to define the custom soap fault message.
- /// Custom SOAP Fault Message class Name :CustomFaultMsg
- /// </summary>
- [DataContract]
- public struct CustomFaultMsg
- {
- /// <summary>
- /// This property is used to pass the custom error information
- /// from service to client.
- /// </summary>
- [DataMember]
- public string MyCustomErrMsg { get; set; }
- }
STEP 2: Attach the SOAP fault on the operation
To make use of the fault messages in our SOAP messages we have attach them to the operations by using "FaultContractAttribute".
- /// <summary>
- /// This is class is exposed as services in WCF programming.
- /// </summary>
- [ServiceContract]
- public interface IService
- {
- /// <summary>
- /// This method is exposed as the operation in WCF.
- /// This method searches for an emp : "empid".
- /// On success it returns the emp details.
- /// On Failure it raises a Fault Message.
- /// </summary>
- /// <param name="EmpId"></param>
- /// <returns></returns>
- [OperationContract]
- [FaultContract(typeof(CustomFaultMsg))]
- Employee GetEmpDetails(string EmpId);
- }
"CustomFaultMsg" is structure for our custom fault. (This is defined in step1).
Here function return type "Employee" is an employee structure. "DataContract" attribute is used to expose this structure in service.
- /// <summary>
- /// This Data Contract structure for holding the Employee details.
- /// </summary>
- [DataContract]
- public struct Employee
- {
- [DataMember]
- public string FName { get; set; }
- [DataMember]
- public string LName { get; set; }
- [DataMember]
- public string DeptID { get; set; }
- [DataMember]
- public string MailID { get; set; }
- [DataMember]
- public string Zip { get; set; }
- }
In the sample program, IService interface is implemented by a class Service. Here the method GetEmpDetails() should raise our own customized exception, whenever it fails to find the employee details.
- /// <summary>
- /// Search the Data Set for an employee of "EmpID".
- /// If the search is successful, then it returns the employee details object to the client.
- /// On an unsuccessful search it throws the customized fault message to the client.
- /// </summary>
- /// <param name="EmpId">Empid</param>
- /// <returns>Employee Object</returns>
- public Employee GetEmpDetails(string EmpId)
- {
- //Search for the "EmpId" employee details in the data set. By using the LINQ ..
- // Add the Dll reference to DataSetExtensions to support for LINQ
- var empRecord = from dr in ds.Tables[0].AsEnumerable()
- where dr["EmpId"].ToString() == EmpId
- select dr;
- // If their are no records, then we have to raise our customized SOAP Fault Message.
- if (empRecord.Count() == 0)
- {
- //create an object for the custom SOAP Fault.
- //and initialize the falut with our own customized fault message.
- CustomFaultMsg custmErr = new CustomFaultMsg {
- MyCustomErrMsg = "There is no employee exist with the emp id : " + EmpId
- };
- //Raise the customized fault message exception to the client.
- throw new FaultException < CustomFaultMsg > (custmErr);
- }
- // if the Emp record is exist , we have to return the emp Details....
- else
- {
- // Create an employee object and store all the emp record details in to the
- // employee object.
- Employee objEmp = new Employee();
- foreach(DataRow dr in empRecord)
- {
- // Emp Id is Unique.
- //So the LINQ select query returns only one row,if the emp exist in the table.
- objEmp.FName = dr["FirstName"].ToString();
- objEmp.LName = dr["LastName"].ToString();
- objEmp.DeptID = dr["DeptId"].ToString();
- objEmp.MailID = dr["MailId"].ToString();
- objEmp.Zip = dr["ZipCode"].ToString();
- }
- //return the employee object to the client.
- return objEmp;
- }
- }


abhishek choudhuryPosted Jan 6, 2013, 9:39 PM
Hi, This is an excellent guide of custom fault contract usage in WCHF. Thank you so much! I am new to the WCF space and am working on a solution that will need to support the old Soap 1.1 exception responses of a web service for backward compatibility. I am able to replicate almost the entire as-is soap exception message except the faultActor tag. Here is how it should look like: <soap:Fault> <faultcode></faultcode> <faultstring></faultstring> <faultactor></faultactor> <detail> <message></message> <description></description> <errorId></errorId> </detail> </soap:Fault> I am able to emulate the entire message except the faultactor tag. Is there some way to use the WCF Fault contracts so as to include a faultactor tag in the exception response? Your inputs are highly appreciated! Regards, Abhishek.
Santosh YadavPosted Jan 4, 2013, 10:53 AM
thank you very much this is a very nice guideline for someone who want to learn fault contract. This is a very useful post thank you again.
Sumit GaudPosted Jun 22, 2012, 2:12 AM
Hi This post is really helpful. I want to send Exception Class object to client. It works fine when program throws user defined exceptions(e.g. throw new Exception ("My Custom Exception");) But when program throw System Exception (e.g. DivideByZeroException). Here is My Code [DataContract] public struct CustomFaultMsg { /// <summary> /// This property is used to pass the custom error information /// from service to client. /// </summary> [DataMember] public Exception _Exception { get; set; } } if Service Method's catch Block catch (Exception ex) { throw new FaultException<CustomFaultMsg> (new CustomFaultMsg { _Exception = ex }); }
Meenakshi RanaPosted Nov 25, 2010, 2:36 AM
very useful, Thanks
Nitesh AroraPosted Mar 2, 2010, 11:47 AM
Thanks for the fantastic article. How would we accomplish this if the client is a non microsoft platform one for example PHP or java?