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.
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.
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:
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).
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.
This website uses cookies. We'll assume you're ok with this, but you can opt-out if you wish.AcceptRead More
Privacy & Cookies Policy
Privacy Overview
This website uses cookies to improve your experience while you navigate through the website. Out of these, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may affect your browsing experience.
Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.
Any cookies that may not be particularly necessary for the website to function and is used specifically to collect user personal data via analytics, ads, other embedded contents are termed as non-necessary cookies. It is mandatory to procure user consent prior to running these cookies on your website.
Don't you think that
if (new string[]{"+", "-", "*", "/"}.Where(x => x == (string) inputs[2]).Count() == 0)
is quite ugly way to write equivalent:
if (new []{"+", "-", "*", "/"}.All(x => x != (string) inputs[2]))
or
if (new []{"+", "-", "*", "/"}.Contains((string) inputs[2]))
??
forgot "logical not" in second case
Andrii, you are right there!
How can we get inputs name in BeforeCall ?