Standard .Net exceptions are correctly serialized on server side, and deserialized on client side.
By default, not ours. Why ?
It may be a best practise to send business exception to client during debuging sessions:
- without having to put the Exception Data in a [DataMember] object
- having more info than a simple string ( ExceptionFault<ExceptionDetail>
)
But take care of not sending exceptions when putting code in production. It may cause security leaks disclosing details to hackers if your service is exposed on internet !
In order to send the business exception to the client, the best (and some mandatory) practises are :
1/ Toggle the serviceDebugBehavior
on
ServiceHost host = ...;
var debuggingBehavior = host.Description.Behaviors.Find<ServiceBehaviorAttribute>();
if (debuggingBehavior == null)
debuggingBehavior = new ServiceBehaviorAttribute();
#if DEBUG
debuggingBehavior.IncludeExceptionDetailInFaults = true;
#else
debuggingBehavior.IncludeExceptionDetailInFaults = false;
#endif
It is also pretty easy configurate it in xml
2/ On the service interface, declare some [FaultContract] :
[ServiceContract(Namespace="your namespace")]
public interface IBillingService
{
[OperationContract]
[FaultContract(typeof(BusinessException))]
void RaiseBusinessException();
}
3/ A business exception should be marked as Serializable
[Serializable]
public class BusinessException : Exception
{ ... }
4/ In order to have a business exception correctly deserialized on the client side as FaultException<BusinessException>
, it is important to implement a constructor taking care of deserialization. Otherwise you'll get a generic FaultException
.
protected BusinessException(SerializationInfo info, StreamingContext context)
: base(info, context)
{}
5/ If you have some extra members in you exception, serialize/deserialize them :
public DateTime CreationTime { get; set; }
protected BusinessException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
CreationTime = (DateTime)info.GetValue("CreationTime", typeof(DateTime));
}
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
info.AddValue("CreationTime", CreationTime);
}