The Windows Communication
Foundation (WCF) application model is designed to solve the greater part of the
communication requirements of any distributed application. But there are always
scenarios that the default application model and system-provided
implementations do not support. Reasons we can go for extension Parameter
Inspection, Message Formatting, Message Inspection, Logging and so on… we can
add as many reasons we want this list is also extendable as per requirement… J In This topic I’ll try to
outlines the various areas of extension let’s start by visiting The WCF Pipe
line…
The WCF Pipeline…
If we have to brief what is
WCF services we can say; Its WCF Messages traveling from server to client or
client to server over The WCF Pipeline.
WCF message is primarily
represented in SOAP \ XML (WCF POX Messages…) format internally & they can
be transferred over the stack in binary or JSON or Plain text format. We can
extend WCF Behaviors at service /
endpoint / contract / operations. Interface exposed are as follows
1) IServiceBehavior 3) IContractBehavior
2) IEndpointBehavior 4) IOperationBehavior
I’ll show example of Implementation
of these Interface while Implementing Message Inspector. Let’s visits Messages
Inspectors …
Messages Inspectors
Message Inspectors are most
used extension in WCF, they allow inspect, modify, logging, Custom Authentication,
Tweaking or replace some message elements in both incoming & out going
messages. At Service side Message Inspectors are implemented using
IDispatchMessageInspector interface which consist followings
- AfterReciveRequest
- BeforeSendReply
Message Inspectors are extended
as end point behaviors
Public void ApplyDispatchBehavior(ContractDescription
contractDescription, ServiceEndpoint endpoint, DispatchRuntime
dispatchRuntime) {
dispatchRuntime.MessageInspectors.Add(new MyInspector());
}
At Client side Message
Inspectors are implemented using IClientMessageInspector interface which
consist followings
- BeforeSendRequest
- AfterReciveReply
It’s added as end point
behaviors
Public void ApplyClientBehavior(ContractDescription
contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime) {
clientRuntime.MessageInspectors.Add(new
MyInspector());
}
Implementation of Message Inspector: - (C# Code
Sample)
Okay let’s implement Message Inspector end
to end... Following is an example of a service-side Message Inspector used to
output to the Console any received and sent message:
public class
ConsoleOutputMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel
channel, InstanceContext instanceContext)
{
MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue);
request = buffer.CreateMessage();
Console.WriteLine("Received:\n{0}",
buffer.CreateMessage().ToString());
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
MessageBuffer buffer = reply.CreateBufferedCopy(Int32.MaxValue);
reply = buffer.CreateMessage();
Console.WriteLine("Sending:\n{0}",
buffer.CreateMessage().ToString());
}
}
In order to configure this message inspector we can extend end point Behavior as follows…
In order to configure this message inspector we can extend end point Behavior as follows…
public class ConsoleOutputBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint,
BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint,
ClientRuntime clientRuntime)
{
throw new Exception("Behavior not supported on the consumer side!");
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint,
EndpointDispatcher endpointDispatcher)
{
ConsoleOutputMessageInspector inspector = new ConsoleOutputMessageInspector();
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
}
public void Validate(ServiceEndpoint endpoint)
{
}
}
As you can see I implement the IEndpointBehavior interface, which defines three methods (AddBindingParameter, ApplyClientBehavior, and
ApplyDispatchBehavior). The one
I'm interested on is the ApplyDispatchBehavior that relates to the service-side. This method receives a parameter
of type EndpointDispatcher that allows adding custom Message Inspectors instance to the
service dispatching environment. Because we're defining an Endpoint Behavior,
this behavior affects a single endpoint of a service. To map the behavior to
the service endpoint we can use a custom configuration element in the
configuration file of the service host. Otherwise we could apply the behavior
directly through the Service
Host instance. In this sample I
used a custom configuration element. To do that we need a custom type describing
the configuration element…It is a type inherited from BehaviorExtensionElement, like the following one:
public class ConsoleOutputBehaviorExtensionElement : BehaviorExtensionElement
{
protected override object CreateBehavior()
{
return new ConsoleOutputBehavior();
}
public override Type BehaviorType
{
get
{
return typeof(ConsoleOutputBehavior);
}
}
}
The previously declared
extension element can be used in the .config file of the service host
application as follows :
<system.serviceModel>
<services>
<service name="Service1">
<endpoint
behaviorConfiguration="ExntBehavior"
address="http://localhost:8000/ Service1"
binding="wsHttpBinding" bindingConfiguration="WsHttpBinding"
contract="IService1" />
</service>
</services>
<system.serviceModel>
<services>
<service name="Service1">
<endpoint
behaviorConfiguration="ExntBehavior"
address="http://localhost:8000/ Service1"
binding="wsHttpBinding" bindingConfiguration="WsHttpBinding"
contract="IService1" />
</service>
</services>
<extensions>
<behaviorExtensions>
<add name="consoleOutputBehavior" type="ConsoleOutputBehaviorExtensionElement,Extensions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
<behaviorExtensions>
<add name="consoleOutputBehavior" type="ConsoleOutputBehaviorExtensionElement,Extensions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
<behaviors>
<endpointBehaviors>
<behavior name="ExntBehavior">
<consoleOutputBehavior />
</behavior>
</endpointBehaviors>
</behaviors>
<endpointBehaviors>
<behavior name="ExntBehavior">
<consoleOutputBehavior />
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="WsHttpBinding">
<security mode="None" />
</binding>
</wsHttpBinding>
</bindings>
<wsHttpBinding>
<binding name="WsHttpBinding">
<security mode="None" />
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
So far you have seen how to
define custom Message Inspector and how to map it to a single endpoint, using
and Endpoint Behavior…
Parameter Inspectors
Parameter Inspectors are similar
to Message Inspector but they used CLR object rather than Message object, they
allow inspect, modify operations inputs & outputs, Logging & Parameter
validation but we can’t modify return value. Parameter Inspectors are
implemented using IParameterInspector interface which consist followings
- BeforeCall
- AfterCall
Implementation of Parameter Inspectors : - (C# Code
Sample)
Public class NameValidationParameterInspector
: IParameterInspector
{
readonly int
_nameParamIndex;
const string
NameFormat ="[a-zA-Z]";
public NameValidationParameterInspector()
: this(0) { }
public NameValidationParameterInspector(int
nameParamIndex)
{
_nameParamIndex
= nameParamIndex;
}
public object
BeforeCall(string operationName, object[] inputs)
{
string
nameParam = inputs[_nameParamIndex] as string;
if
(nameParam != null)
if
(!Regex.IsMatch(
nameParam,
NameFormat, RegexOptions.None))
throw
new FaultException(
"Invalid
name. Only alphabetical character");
return
null;
}
public void
AfterCall(string operationName, object[] outputs, object returnValue, object correlationState){}
}
Rest we can decide on which
Behaviour we want to extend it and
then we can modify our configuration, or service attributes as per need..
Implementation would be same as we have done in implementation of Message
Inspector….
Though you might not
directly need to extend the functionality of WCF it’s nice to know that it’s
possible and extremely flexible. The scenario for extending WCF’s functionality
might come in handy when you need to apply instrumentation. E.g.: Parameter and
Message Inspectors might come in handy for logging every incoming and outgoing
parameter and message…
Courtesy: Random Web Images, Microsoft .NET 3.5 WCF Book, Several online
resources
No comments:
Post a Comment