IDispatchOperationSelector–How to assign messages to operations?

Posted on December 12, 2010 by

0


When working with SOAP messages the dispatching in the server side is done according to the soap action header, which instructs the dispatcher what is the corresponding method which should handle the message.

When there is a need to override the default way the server assigns incoming messages to operations, the IDispatchOperationSelector should be overridden.

IDispatchOperationSelector has only one method in its interface which should be implemented:

public interface IDispatchOperationSelector
{
    string SelectOperation(ref System.ServiceModel.Channels.Message message);
}
 

In order to add a new dispatcher just inherit from IContractBehavior and add the dispatcher in the server side as follows:

    public class DispatchByBodyElementBehavior : IContractBehavior
    {
        ....
        
        public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
        {

            dispatchRuntime.OperationSelector = new DispatchByBodyElementOperationSelector(
                         GetSelectorDictionary(contractDescription.Operations));
        }
        
        private static Dictionary<string, string> GetSelectorDictionary(IEnumerable<OperationDescription> operationDescriptionCollection)
        {
          ....
        }
    }

IDispatchOperationSelector Sample

In the sample below, the dispatcher receives in its constructor a dictionary which maps the name of the first element inside the SOAP body to an operation name to which the message will be forward for processing.

    public class DispatchByBodyElementOperationSelector : IDispatchOperationSelector
    {
        #region fields

        private const string c_default = "default";
        readonly Dictionary<string, string> m_dispatchDictionary;

        #endregion

        #region constructor

        public DispatchByBodyElementOperationSelector(Dictionary<string, string> dispatchDictionary)
        {
            m_dispatchDictionary = dispatchDictionary;
            Debug.Assert(dispatchDictionary.ContainsKey(c_default), "dispatcher dictionary must contain a default value");
        }

        #endregion

        public string SelectOperation(ref Message message)
        {
            string operationName = null;
            var bodyReader = message.GetReaderAtBodyContents();
            var lookupQName = new
               XmlQualifiedName(bodyReader.LocalName, bodyReader.NamespaceURI);

            // Since when accessing the message body the messageis marked as "read"
            // the operation selector creates a copy of the incoming message 
            message = CommunicationUtilities.CreateMessageCopy(message, bodyReader);

            if (m_dispatchDictionary.TryGetValue(lookupQName.Name, out operationName))
            {
                return operationName;
            }
            return m_dispatchDictionary[c_default];
        }
    }

Advertisements
Posted in: WCF Extensions