Wednesday, April 25, 2012

How to Implement a Custom WCF Data Service (OData) Message Handler

Summary of Steps 
  1. In order to create a message handler you need to create a class that implement  IDispatchMessageInspector   interface 
  2. Next you need to create an attribute class that implements ' IServiceBehavior ' interface and bind your Inspector class created above.

Overview 
Message handlers are invoked before request is submitted to WCF Data Service Runtime and after the response is ready to be replayed

Uses of Message Handlers 
Message handlers can rescue you from various customization scenario, It is particularly useful when you need to we need to inject some custom logic in the response generated by WCF Data service. 
One example can be found in my CodePlex project WCF Format Extensions for CSV, TXT

Steps By Step                                               
  • Add a new Class library project "WCFDataServiceCustomHandler"
  • Add two references System.ServiceModel.dll and System.ServiceModel.Channels.dll in library project
  • Add two classes CustomMessageInspector and EnableCustomHandler
  • Implement class   CustomMessageInspector  as below 
public class CustomMessageInspector :IDispatchMessageInspector
    {
       public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
        {
            Debug.WriteLine("AfterReceiveRequest:" + request.Properties.Via.AbsoluteUri);
            return "MyCustomToken";
        }

        public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
        {
           if (correlationState is string &&"MyCustomToken" == (string)correlationState  )
            {
                    Debug.WriteLine("BeforeSendReply Invoked ");
            }
        }
    }

  • Implement Class  EnableCustomHandler as below 
[AttributeUsage(AttributeTargets.Class)]
    public class EnableCustomHandler : Attribute, IServiceBehavior
    {
        void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
        {
            //Nothing TO DO
        }

        void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers)
            {
                foreach (EndpointDispatcher ed in cd.Endpoints)
                {
                    ed.DispatchRuntime.MessageInspectors.Add(new CustomMessageInspector());
                }
            }
        }

        void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            //Nothing TO DO
        }
    }

  • Now Apply  EnableCustomHandler  Attribute to your service class 
[EnableCustomHandler]
    public class WcfDataService1 : DataService< NORTHWNDEntities >

  • Run your Service and Navigate to entity URL  (See output below)
BeforeSendReply Invoked
Alternative Titles 
  • WCF Data Service Message Handler Code Samples 
  • How to use  Data Service Message Handler

1 comment:

  1. Thanks for the sample! I like this approach for the WCF Data Services 5.0 upgrade and Chrome problem that you helped on in the forum (http://social.msdn.microsoft.com/Forums/en/adodotnetdataservices/thread/8160809a-5564-4b9a-b7ea-84faa4ced7e4?prof=required)

    ReplyDelete