Introduction
What is the use of FaultContract?
In simple WCF Service errors/Exceptions can be passed to the Client(WCF Service Consumer) by using FaultContract
How do you handle errors in ASP.NET? It's very simple just by adding the simple Try & Catch blocks. But when you come to WCF Service if any unexpected error occurred (like SQL server down/Unavailability of data/Divide By Zero) in service then error/Exception details can be passed to Client by using Fault Contract.
False Assumption
Most of people think that we can't throw FaultException in catch block. It should be only based on some conditon (if condition). But it is false assumption. The main objective is, any type of exceptions(Predicted or Unpredicted) from service to be passed to Client(WCF Service consumer).
Predicted:(Divide By Zero/Channel Exceptions/Application exceptions etc..)
public void Divide(float number, float divideBy)
{
If(dividBy ==0)
{
myServiceData.Result = false;
myServiceData.ErrorMessage = "Invalid Operation.";
myServiceData.ErrorDetails = "Can not divide by 0.";
throw new FaultException<ServiceData>(myServiceData);
}
return number/divideBy;
}
UnPredicted: (which I explained in this article like connection failures/SQL Server down/Transport errors/Business logic errors.)
try
{
SqlConnection con = new SqlConnection(StrConnectionString);
con.Open();
myServiceData.Result = true;
}
catch (SqlException sqlEx)
{
myServiceData.Result = true;
myServiceData.ErrorMessage = "Connection can not open this " +
"time either connection string is wrong or Sever is down. Try later";
myServiceData.ErrorDetails = sqlEx.ToString();
throw new FaultException<ServiceData>(myServiceData, sqlEx.ToString());
}
catch (Exception ex)
{
myServiceData.Result = false;
myServiceData.ErrorMessage = "unforeseen error occured. Please try later.";
myServiceData.ErrorDetails = ex.ToString();
throw new FaultException<ServiceData>(myServiceData, ex.ToString());
}
Using the Code
This is a very simple WCF service implementation to understand the usage of the FaultContract. Here I am implementing the TestConnection() method
in the WCF service. This method try to open some SQL Server connection if any errors occurs while opening the connection it throws the error details to the cleint
by using the Fault Contract.
Here my solution contain 2 projects
- Service Implementation in ASP.NET
- Consuming the service in Console application
Note:
This article not written to test the connection string. This is to understand
the usage of FaultContract. So I taken this basic example to explain you better.
1. Service Implementation
Create a WCF Service application project & Implement the service with the following code.
The TestConnection() method added with FaultContract attribute in IService1 interface.
It means that service errors should be passed to the client with the type of ServiceData class.
ServiceData class is DataContract class. The Error & Success message details to be added to this data members.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace FaultContractSampleWCF
{
[ServiceContract]
public interface IService1
{
[OperationContract]
[FaultContract(typeof(ServiceData))]
ServiceData TestConnection(string strConnectionString);
}
[DataContract]
public class ServiceData
{
[DataMember]
public bool Result { get; set; }
[DataMember]
public string ErrorMessage { get; set; }
[DataMember]
public string ErrorDetails { get; set; }
}
}
Here I am implementing the IService1 interface. This interface contain only one method TestConnection() with one input
parameter StrConnectionString. For this input parameter SQL Server connection details should be passed from the client side.
Note: This example only to understand the basic use of Fault Contract. This article doesn't concentrated on service security.
You can try this article from your localhost SQL connection by passing valid & Invalid connection string details.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Data.SqlClient;
namespace FaultContractSampleWCF
{
public class Service1 : IService1
{
public ServiceData TestConnection(string StrConnectionString)
{
ServiceData myServiceData = new ServiceData();
try
{
SqlConnection con = new SqlConnection(StrConnectionString);
con.Open();
myServiceData.Result = true;
con.Close();
return myServiceData;
}
catch (SqlException sqlEx)
{
myServiceData.Result = true;
myServiceData.ErrorMessage = "Connection can not open this " +
"time either connection string is wrong or Sever is down. Try later";
myServiceData.ErrorDetails = sqlEx.ToString();
throw new FaultException<ServiceData>(myServiceData, sqlEx.ToString());
}
catch (Exception ex)
{
myServiceData.Result = false;
myServiceData.ErrorMessage = "unforeseen error occured. Please try later.";
myServiceData.ErrorDetails = ex.ToString();
throw new FaultException<ServiceData>(myServiceData, ex.ToString());
}
}
}
}
Web.config
Note: The following endpoint details automatically added to web.cofig when you create a WCF Service Project.
<services>
<service name="FaultContractSampleWCF.Service1"
behaviorConfiguration="FaultContractSampleWCF.Service1Behavior">
-->
<endpoint address="" binding="wsHttpBinding" contract="FaultContractSampleWCF.IService1">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
2. Consuming the service in Console application
Create a new Console project and give the above service reference. Here we are creating a object to the Service1Client class
and calling the TestConnection() method by passing the connection string. If connection succeeds then it shows "Connection Succeeded" message.
If unable to open connection then it moves to the catch block and displays the appropriate error.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Client_FaultContractSampleWCF.MyServiceRef;
using System.ServiceModel;
namespace Client_FaultContractSampleWCF
{
class Program
{
static void Main(string[] args)
{
try
{
Service1Client objServiceClient = new Service1Client();
ServiceData objSeviceData = objServiceClient.TestConnection(
@"integrated security=true;data source=localhost;initial catalog=master");
if (objSeviceData.Result == true)
Console.WriteLine("Connection Succeeded");
Console.ReadLine();
}
catch (FaultException<ServiceData> Fex)
{
Console.WriteLine("ErrorMessage::" + Fex.Detail.ErrorMessage + Environment.NewLine);
Console.WriteLine("ErrorDetails::" + Environment.NewLine + Fex.Detail.ErrorDetails);
Console.ReadLine();
}
}
}
}
Summary:
Hope that this article is useful to understand the usage of the FaultContract. This article is focus on how to implement a basic WCF service and how to handle the errors.
Please don't forgot to rate it if you like.