31 January 2018 wcf Robert Muehsig

If you are still using WCF you might have stumbled upon this problem: WCF allows you to throw certain Faults in your operation, but unfortunatly it is a bit awkward to configure if you want “Global Fault Contracts”. With this solution here it should be pretty easy to get “Global Faults”:

Define the Fault on the Server Side:

Let’s say we want to throw the following fault in all our operations:

[DataContract]
public class FoobarFault
{

}

Register the Fault

The tricky part in WCF is to “configure” WCF that it will populate the fault. You can do this manually via the [FaultContract-Attribute] on each operation, but if you are looking for a global WCF fault configuration, you need to apply it as a contract behavior like this:

[AttributeUsage(AttributeTargets.Interface, AllowMultiple = false, Inherited = true)]
public class GlobalFaultsAttribute : Attribute, IContractBehavior
{
    // this is a list of our global fault detail classes.
    static Type[] Faults = new Type[]
    {
        typeof(FoobarFault),
    };

    public void AddBindingParameters(
        ContractDescription contractDescription,
        ServiceEndpoint endpoint,
        BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyClientBehavior(
        ContractDescription contractDescription,
        ServiceEndpoint endpoint,
        ClientRuntime clientRuntime)
    {
    }

    public void ApplyDispatchBehavior(
        ContractDescription contractDescription,
        ServiceEndpoint endpoint,
        DispatchRuntime dispatchRuntime)
    {
    }

    public void Validate(
        ContractDescription contractDescription,
        ServiceEndpoint endpoint)
    {
        foreach (OperationDescription op in contractDescription.Operations)
        {
            foreach (Type fault in Faults)
            {
                op.Faults.Add(MakeFault(fault));
            }
        }
    }

    private FaultDescription MakeFault(Type detailType)
    {
        string action = detailType.Name;
        DescriptionAttribute description = (DescriptionAttribute)
            Attribute.GetCustomAttribute(detailType, typeof(DescriptionAttribute));
        if (description != null)
            action = description.Description;
        FaultDescription fd = new FaultDescription(action);
        fd.DetailType = detailType;
        fd.Name = detailType.Name;
        return fd;
    }
}	

Now we can apply this ContractBehavior in the Service just like this:

[ServiceBehavior(...), GlobalFaults]
public class FoobarService
...

To use our Fault, just throw it as a FaultException:

throw new FaultException<FoobarFault>(new FoobarFault(), "Foobar happend!");

Client Side

On the client side you should now be able to catch this exception just like this:

    try
	{
		...
	}
	catch (Exception ex)
	{
		if (ex is FaultException faultException)
		{
			if (faultException.Action == nameof(FoobarFault))
			{
			...
			}
		}
	}

Hope this helps!

(This old topic was still on my “To-blog” list, even if WCF is quite old, maybe someone is looking for something like this)


Written by Robert Muehsig

Software Developer - from Dresden, Germany, now living & working in Switzerland. Microsoft MVP & Web Geek.
Other Projects: KnowYourStack.com |ExpensiveMeeting | EinKofferVollerReisen.de

If you like the content and want to support me you could buy me a beer or a coffee via Litecoin LV944KWxEM3WaCYCUKJMiLtfRrXPd8Cnbh or Bitcoin 1C712oGPrTLmDjQ7SHjh6TGqchQdCzo2Sn - thanks for reading!


blog comments powered by Disqus