Ferry Mulyono

See also: Other Geeks@INDC

WCF Client Message Inspector

I've been playing around a little with WCF, and will play it a lot next month (for my thesis). I've been wondering how can I 'capture' the SOAP message before it is sent. After two hours scratching my head and digging through MSDN, finally I get it done.

So basically, I want to try to display the SOAP message sent to the service host. In order to do this, you might want to pay attention to 3 things:

·         System.ServiceModel.Configuration.BehaviorExtensionElement

·         System.ServiceModel.Description.IEndpointBehavior

·         System.ServiceModel.Dispatcher.IClientMessageInspector

First step, we need to create the ‘proxy’, the one that will actually show the message before it’s sent to the service host (you can even modify the message here. There’s one post that actually shows ‘message tampering’ example with WCF). Anyway, so in my case, I would like to display the message to the console. Below is the code.

class MyMessageInspector : System.ServiceModel.Dispatcher.IClientMessageInspector

    {

        #region IClientMessageInspector Members

        public void AfterReceiveReply(ref Message reply, object correlationState)

        {   // Ignore

        }

        public object BeforeSendRequest(ref Message request, IClientChannel channel)

        {

            Console.WriteLine(request.ToString());

            return null;

        }

        #endregion

    }

Next, we should ‘tell’ the WCF runtime (or WCF message pipeline in this matter), to go through this message inspector first before sending the message. I decided to attach it in ‘endpoint layer’, by implementing interface System.ServiceModel.Description.IEndpointBehavior.  In ApplyClientBehavior method, there’s a ClientRuntime typed parameter that we can use to ‘attach’ our message inspector (through its property called MessageInspectors).

Okay, we’ve done the part where we attach the message inspector to the endpoint, but how can we ‘attach’ this endpoint behavior to the auto-generated proxy (piece of code that will actually serialize the request and send it to service host)? One way I found is using the configuration, but before that we need to implement System.ServiceModel.Configuration.BehaviorExtensionElement (to process the configuration node). The implementation is quite straight forward; just override two methods that basically requesting description of the endpoint behavior (the one in the previous paragraph) and its instance.

public class MyMessageInspectionBehavior : System.ServiceModel.Configuration.BehaviorExtensionElement, System.ServiceModel.Description.IEndpointBehavior

    {

        #region IEndpointBehavior Members

        public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)

        { // Ignore

        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)

        {

            clientRuntime.MessageInspectors.Add(new MyMessageInspector());

        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)

        { // Ignore

        }

        public void Validate(ServiceEndpoint endpoint)

        { // Ignore

        }

        #endregion

        public override Type BehaviorType

        {

            get { return typeof(MyMessageInspectionBehavior); }

        }

        protected override object CreateBehavior()

        {

            return new MyMessageInspectionBehavior();

        }

    }

Note: I was too lazy to separate the endpoint behavior code and behavior extension element code, so I merge it.

The last step, is to write the configuration file

<client>

  <endpoint

    address="http://localhost:8080/SampleService"

    behaviorConfiguration="clientInspectorsAdded"

    binding="wsHttpBinding"

    bindingConfiguration="WSHttpBinding_ISampleService"

    contract="ISampleService"

    name="WSHttpBinding_ISampleService"

      >

  </endpoint>

</client>

<behaviors>

  <endpointBehaviors>

    <behavior name="clientInspectorsAdded">

      <clientInterceptors />

    </behavior>

  </endpointBehaviors>

</behaviors>

<extensions>

  <behaviorExtensions>

    <add

      name="clientInterceptors"

      type="Microsoft.WCF.Documentation. MyMessageInspectionBehavior, HostApplication, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"

  />

  </behaviorExtensions>

</extensions>

Note: Again, I was too lazy to rearrange my code to paste it here, so I picked the one from MSDN =p

Anyway, it’s done. After doing steps above, try to debug your WCF client app. It’ll stop when you execute the service code, but what it actually does is giving you chance to process/display the message before it’s actually sent (using message inspectors).

At first I thought I could do it using Fiddler, but I can’t seem find a way to redirect the WCF proxy to Fiddler proxy (maybe because WCF supports not only HTTP channel, but also TCP and MSMQ, so Fiddler proxy might not be able to forward the request to other channel than HTTP channel).

In the end, this is the only thing I could come up with. If any of you got any easier way, I would definitely use it =)

References

http://msdn2.microsoft.com/en-us/library/system.servicemodel.dispatcher.iclientmessageinspector.aspx

http://msdn2.microsoft.com/en-us/library/ms733786.aspx

http://blogs.msdn.com/kaevans/archive/2006/10/01/779886.aspx

http://blogs.msdn.com/drnick/archive/2007/03/07/message-flow-interception-points.aspx

Share this post: | | | |
Posted: Apr 27 2007, 04:12 AM by ferry | with 1 comment(s)
Filed under: ,

Comments

Ferry Mulyono said:

&quot;Alternative&quot; to server side message inspector of WCF: WCF Client Message Inspector Anyone

# April 27, 2007 11:21 AM