Introduction to Extensibility
Extensibility = Extend the functionality.
Guys, before we jump into WCF Extensibility, I would like to give you, a brief on extensibility, which is nothing but a software design principle to extend the software functionality with minimal impact or no impact into the existing functionalities. In simple words, Feature X would not be affected by the extended Feature Y.
WCF pipeline is easily extendable, which allows the developer to extend in various locations in the Client and the Service to implement the custom logic, if required. You can extend your own binding, channel and behavior. Let us discuss this in detail.
WCF Service Stack
I would suggest you to read my old article WCF Runtime Architecture and SOA implementation to understand WCF pipeline architecture completely before you jump into extensibility. In the snapshot given below, you can understand the processes involved in sending the data from the client to the Server and vice versa.
The data travels from the client Application to the stream by converting calls to WCF message, converts the messages into the calls and objects on the Server side. There are five extensible endpoints on the Server side.
- Message Inspection
- Operation Selector
- Message Formatting (De-Serialization)
- Parameter Inspection and
- Operation Invoker
WCF has multiple extensible points, which allows you to modify the runtime behavior. You can ask me a question like, what is the usage of extensible points? Why should I modify the runtime behavior, using the extensible points? The snapshot given below answers these questions.
From the Message Inspector, you can find
- How much data exchanged between the Client and the Server?
- What is the size of the Message?
- How long will it take to reach the message from the Client to the Server?
- How much time the Service Method will take to process it?
From the Parameter Inspector, you can find
- Which clients are making calls to the Service?
- Is the User an Authenticated one?
In this article, we are going to see Message Inspector in detail.
Message Inspector
Message Inspector is the most extensively used extensible point, which allows the developer to log, modify and replace the complete message. The two interfaces given below help us to log and modify the messages in WCF pipeline.
- IDispatchMessageInspector
- IClientMessageInspector
The implementation of IDispatchMessageInspector- AfterRecieveRequest method helps us to inspect the incoming message, which is received on the wire and before that, it is dispatched to the Service method. The implementation of IDispatchMessageInspector-BeforeSendReply method helps us to receive the outgoing message from the Service method and before that, it is sent on the wire.
The implementation of IClientMessageInspector-BeforeSendRequest method helps us to receive and inspect the message, which is created from the client Application and before that, it is sent to the wire. IClientMessageInspector-AfterRecieveReply method helps us to receive the message (response message) from the Server and before that, it reaches the client application. Let us talk about it in detail.
Configure Message Inspectors
Step 1
Create a separate class library and refer the assemblies and namespaces given below.
- System.ServiceModel
- System.Runtime.Serialization
Now, implement IDispatchMessageInspector methods AfterRecieveRequest and BeforeSendReply. AfterRecieveRequest helps us to identify, log, modify or replace the incoming message, which is received from the client and before that, it is sent to the Service method.
In the snapshot given above, you can see the parameters Message (reference param), Channel and InstanceContext. Channel parameter helps us to identify through which channel (basicHttp, netTcp) the message is received. With the help of InstanceContext parameter, you can find out any InstanceContext(PerCall,PerSession) associated with this Service.
The message object is passed by the reference. The beauty of the message object is that once you consume (read, write, copied) the object, it cannot be used again. The message object is read once in the stream. Once consumed; it cannot be used again. The responsibility of the Message Inspector’s responsibility is to recreate the message.
The source stated above shows how the message is consumed and recreated. In our case, I have not changed the original data. I have recreated the original data. The methods shown below would cause the message to consume.
- CreateBufferedCopy
- GetBody
- GetReaderAtBodyContents
- WriteBody
- WriteBodyContents
- WriteMessage
Accessing the message headers and properties does not have any issues; accessing the message object once will be treated as consumed and it cannot be consumed again.
Step 2
In order to add Message Inspector, we have to create a custom behavior extension class, which is derived from IServiceBehaviour or IEndpointBehaviour, In our case, I will implement IEndpointBehaviour.
In the snapshot, mentioned above, you can find that IEndpointBehaviour is implemented ApplyDispatchBehaviour and other methods. You need to create the Message Inspector object and add into Endpoint Dispatcher.
Finally, you need to create the Behavior extension class, which is derived from BehaviourExtensionElement, override the CreateBehaviour method and BehaviourType property to return the MessageEndPtBehaviour objects (custom behavior objects).
Step 3
As the last step, we have to update the behavior settings in the App.config file as well.
In the snapshot, mentioned above, please mention the name of the extension, type and assembly name. Assign the extension name "InspectorExtension" into the endpointBehaviour as well.
Please refer the attached source code for more details.
Output
Please refer the ServiceInspector library in the Host Application and Host the Server. If you clearly notice the output, once the Client is launched; in the Application you can find that before the log is placed in, the Service method triggers and the log I placed in the ServiceInspector gets triggered.
In the snapshot shown above, "PNR Query processing" and "PNR Query processed" are the logs placed inside the Service Method and get triggered only after the execution of AfterReceiveRequest method in the ServiceInspector. Please refer to the attached source code for more details.
Summary
To inspect the messages in the WCF pipe line, the IDispatchMessageInspector and IClientMessageInspector interfaces implement methods AfterRecieveRequest and BeforeSendReply in the service side, to receive and inspect the incoming messages and outgoing messages. WCF run time behavior can be easily extended with the help of extensibility.