Let’s take a look how we use one of the instruments of the WCF, called Parameter Inspector.
Here below we see how message request goes between Client and Service.
image
Let’s now imagine that we have some kind of calculator on service side, that has method string Execute(int a, int b, string operation). Client should be very careful in passing parameters to the service, because service is developed by some other team, and after you pass incorrect parameters it fails.
It turns out that with WCF services we are not required to implement such logic before calling method. It can be applied to your request when passing to service. Either just before passing it to channel stack at client or at dispatcher after it came from network on server.
On the picture below we see more closely what is at proxy layer, and 3 points where you can inject your logic.
image So moving forward I’m going to implement Parameter Inspection for my calculator example.
Here is implementation of my calc service. Please take a look that for this naive example, I’m killing process when operation is not available. Of course in standard situation with WCF we would probably throw fault exception and catch it on client side. But for now, lets assume that there is some super logic on service and we cannot change calculator code – it stops working is we pass wrong operation string.
    public class CalculatorService : ICalculatorService
    {
        public int Execute(int a, int b, string operation)
        {
            Console.WriteLine("Received request: ({0}{2}{1}=?)", a, b, operation);

            int result = -1;
            switch (operation)
            {
                case "+":
                    result = a + b;
                    break;
                case "-":
                    result = a - b;
                    break;
                case "*":
                    result = a * b;
                    break;
                case "/":
                    result = a / b;
                    break;
                default:
                    Console.WriteLine("Our calc executed hara-kiri.");
                    Process.GetCurrentProcess().Kill();
                    break;
            }
            return result;
        }
    }
Client is the most standard, that you can imagine, it asks calculator for answer by passing parameters entered in console in while loop.
                        var res = calculatorServiceClient.Execute(a, b, op);
                        Console.WriteLine(res);
Now let see how calc crashes on ‘@’ operation:
image We want to execute parameters verification before calling method on server, and if parameters do not satisfy us, we abort calling calculator. For this I simply surround call to the service in my client in following way:
                    try
                    {
                        var res = calculatorServiceClient.Execute(a, b, op);
                        Console.WriteLine(res);
                    }
                    catch (ArgumentException exception)
                    {
                        Console.WriteLine(exception.Message);
                    }
So how do we get ArgumentException on client? We add custom behavior to the client endpoint.
            using (var calculatorServiceClient = new CalculatorServiceClient("WS2007HttpBinding_ICalculatorService"))
            {
                calculatorServiceClient.Endpoint.Behaviors.Add(new CustomEndpointBehavior());

                calculatorServiceClient.Open();
                
                // ... 
So custom behavior allows us add operation, message and parameter inspectors. In my example I will only add parameter inspector. See below:
    public class CustomEndpointBehavior : IEndpointBehavior
    {
        public void Validate(ServiceEndpoint endpoint)
        {
            return;
        }

        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
            return;
        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
            return;
        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            foreach (var clientOperation in clientRuntime.Operations)
            {
                clientOperation.ParameterInspectors.Add(new OpParameterInspector());
            }
        }
    }

    public class OpParameterInspector : IParameterInspector
    {
        public object BeforeCall(string operationName, object[] inputs)
        {
            switch (operationName)
            {
                case "Execute":
                    VerifyExecuteParams(inputs);
                    break;
            }

            return null;
        }

        private void VerifyExecuteParams(object[] inputs)
        {
            if (new string[]{"+", "-", "*", "/"}.Where(x => x == (string) inputs[2]).Count() == 0)
            {
                throw new ArgumentException("Your operation should belong to folowing list: '+', '-', '*', '/'. Please verify and try again.");
            }
        }

        public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
        {
            return;
        }
    }
And as result of our work we got parameters validation, not completely in client code and not on server, but somewhere in the middle (yeah, it is still client, but validation is postponed to next step in WCF pipeline – Proxy).
image
While learning WCF I wonder how many different extensions and flexibility it allows. Not sure if it all is needed, but if you have doubts if WCF can or cannot do something, be sure – it can.