Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WCF: Same Faultcontract on many methods

Take for example a project with 10 services and 20 methods on each service.

All services inherit from a base services which has a security check. The first thing each method does is to make a call to the security check. This throws a security exception if there is a problem.

Question is: Do I need to specify a FaultContract on each method (OperationContract), or can I do it once in a central definition?

like image 770
Shiraz Bhaiji Avatar asked Sep 08 '09 07:09

Shiraz Bhaiji


People also ask

What is difference between communication exception and FaultException in WCF?

In a WCF service, if it throws an exception inside the service, the client will not get the details. In order to get the formatted exception details on client side, you need to use FaultException instead to let the client know the details. The FaultException information can be serialized as expected.

What is a FaultException?

Fault exceptions are triggered when the processor detects an error such as the execution of an undefined instruction, or when the bus system returns an error response to a memory access.


2 Answers

You can do it by creating a custom attribute.

Implement IContractBehavior and add the fault to each operation on the Validate method.

void IContractBehavior.Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
   foreach (OperationDescription od in contractDescription.Operations)
      od.Add(yourFault);
}

Here's a link that details how to achieve this. Below the actual code to use:

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

    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;
    }
}
like image 165
cocogza Avatar answered Nov 15 '22 19:11

cocogza


No, you need to do it on each and every method - WCF is rather picky and requires explicit settings pretty much for everything (which really is a good thing in the end, I am convinced).

Marc

like image 21
marc_s Avatar answered Nov 15 '22 19:11

marc_s