How to add behavior to client endpoint in IIS Hosted WCF Service using ServiceHostFactory

Sandeep Polavarapu picture Sandeep Polavarapu · Jul 2, 2013 · Viewed 10k times · Source

I am looking at implementing IDispatchMessageInpector & IClientMessageInpector to look at the message objects in AfterReceiveRequest and BeforeSendRequest Methods. My requirement is to make changes at code level of WCF service. No Configuration Changes. How to attach this behaviour to all the endpoints which are calling this service and to service itself. Is implementing IContractBehaviour helps me?

Edit 1: WCF Service is hosted on IIS. Is it possible to add the behavior thru code?

Edit 2: Seems like using ServiceHostFactory we can achieve this. How can i add behavior to client endpoint which are defined in webconfig?

Answer

vibhu picture vibhu · Jul 2, 2013

yes, it is possible to add behavior for services hosted in IIS. Behaviors are not concerned with the hosting environment of the service. Carlos Figueira's blog provides examples of all types of behaviors you could apply to Service, Endpoints, Contracts and Operations. A sample code that I tried for my service hosted in IIS (with endpoint defined in web.config file) - Config file here needs to add the behavior as ExtensionElement

public class MyEndpointBehavior : BehaviorExtensionElement, IEndpointBehavior
{
            public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
            {
                Console.WriteLine("applying dispatch behavior");
                endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new MyInspector());
                endpointDispatcher.DispatchRuntime.OperationSelector = new MyOperationSelector();
            }

        public void  AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
        }

        public void  ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
        }

        public void  Validate(ServiceEndpoint endpoint)
        {
        }

        public override Type BehaviorType
        {
            get {  return this.GetType(); }
        }

        protected override object CreateBehavior()
        {
           return new MyEndpointBehavior();
        }
}

    public class MyOperationSelector : IDispatchOperationSelector
    {
        public string SelectOperation(ref Message message)
        {
            Console.WriteLine("good luck");
            string action = message.Headers.Action;
            return action.Substring(action.LastIndexOf('/') + 1);
        }
    }

    public class MyInspector : IDispatchMessageInspector
    {

        public object AfterReceiveRequest(ref Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
        {
            return (Message) request;
        }

        public void BeforeSendReply(ref Message reply, object correlationState)
        {
        }
    }
 }

Config file with behavior added as extension element -

  <system.serviceModel>
  <services>
  <service name="RouteToServiceA.Service1">
    <endpoint address="Service1" binding="basicHttpBinding" contract="RouteToServiceA.IService1" behaviorConfiguration="testEndPoint" />
  </service>
</services>
<behaviors>
  <serviceBehaviors>
    <behavior>
      <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
      <serviceMetadata httpGetEnabled="true" />
      <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
      <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>
  </serviceBehaviors>
  <endpointBehaviors>
    <behavior name="testEndPoint">
      <testBehavior />
    </behavior>
  </endpointBehaviors>
</behaviors>
<extensions>
  <behaviorExtensions>
    <add name="testBehavior" type="RouteToServiceA.MyEndpointBehavior, RouteToServiceA" />
  </behaviorExtensions>
</extensions>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
 </system.serviceModel>