WCF Message inspector is not working
Asked Answered
P

1

1

Recently, I was exploring some way to log any requests/responses that my WCF service handles.

Before that I have some bad experience with an trace option. Nowadays, I don't know yet how to get actual responses and requests from trace (I tried svctraceviewer tool and it didn't get something meaningful for me). And even that, trace file got generated corrupted (with some unexpectable chars in it).

I figured out about message inspectors technology about three or four days ago. I read this manual and implemented client-side message inspector in other my project. Actually I could see any request my wcf client sent and other-side service response for that request.

I hope it same easy to do another side logging (e.g. get service requests from clients and server responses for them). But I coldn't . Here is details:

public class LogMessageBehavior : IEndpointBehavior
{
    public LogMessageBehavior() 
    { }

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

    public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
    {
        throw new NotImplementedException();
    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
    {
        LogMessageInspector inspector = new LogMessageInspector();
        endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
    }

    public void Validate(ServiceEndpoint endpoint) 
    { 
    }

}

public class LogMessageBehaviorExtensionElement : BehaviorExtensionElement
{
    public LogMessageBehaviorExtensionElement() { }

    public override Type BehaviorType
    {
        get
        {
            return typeof(LogMessageBehavior);
        }
    }

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

public class LogMessageInspector : IDispatchMessageInspector
{
    object IDispatchMessageInspector.AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
    {
        throw new NotImplementedException();
    }

    void IDispatchMessageInspector.BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
    {
        throw new NotImplementedException();
    }
}

Almost all code stubbed with NotImplementedException, but I set breakpoints on every method and property. Further I will tell how they got hit.

App.config

<?xml version="1.0"?>
<configuration>
  <system.serviceModel>
    <extensions>
      <behaviorExtensions>
        <add name="LogMessage" type="MyService.Extensions.LogMessageBehaviorExtensionElement, MyServiceApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
      </behaviorExtensions>
    </extensions>
    <behaviors>     
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="True"/>
          <serviceDebug includeExceptionDetailInFaults="True"/>          
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="LogMessageEndpointBehavior">
          <LogMessage />
        </behavior>
      </endpointBehaviors>
    </behaviors>

    <diagnostics>
      <messageLogging
           logEntireMessage="true"
           logMalformedMessages="true"
           logMessagesAtServiceLevel="true"
           logMessagesAtTransportLevel="true"
           maxMessagesToLog="3000"
           maxSizeOfMessageToLog="20000"/>
    </diagnostics>
    <!-- omitted for brewity -->
    <services>
      <service name="MyService">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8733/"/>
          </baseAddresses>
        </host>
        <endpoint address="MyServiceAddress" binding="basicHttpBinding" bindingConfiguration="MyService" contract="MyService" name="MyService"  behaviorConfiguration="LogMessageEndpointBehavior">
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>

    <bindings>
      <basicHttpBinding>
        <binding name="MyService" closeTimeout="00:01:00"
          openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
          allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
          maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
          messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
          useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
            maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <security mode="Transport">
            <transport clientCredentialType="None" proxyCredentialType="None"
              realm="" />
            <message clientCredentialType="UserName" algorithmSuite="Default" />
          </security>
        </binding>
       <!-- omitted for brewity -->
      </basicHttpBinding>
    </bindings>
  </system.serviceModel>

  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel.MessageLogging">
        <listeners>
          <add name="messages"
          type="System.Diagnostics.XmlWriterTraceListener"
          initializeData="C:\messages.svclog" />
        </listeners>
      </source>
    </sources>
  </system.diagnostics>

</configuration>

Here is how the service installs:

ServiceHost myserviceHost = new ServiceHost(typeof(MyService), new Uri(Environment.bindAddress));            
myserviceHost.Open();

Console.WriteLine(myserviceHost.BaseAddresses[0]);
Console.ReadLine();

Service class is without any something special.

So, how is this construction works. As I mentioned before, I set breakpoints in every method and property. And after I start debugging, we got breakpoints hits in this order:

1. public LogMessageBehaviorExtensionElement() { } 
2. get { return typeof(LogMessageBehavior);  }
3. get { return typeof(LogMessageBehavior);  } (again)
4. get { return typeof(LogMessageBehavior);  } (again)
5. get { return typeof(LogMessageBehavior);  } (again)

OK, let try send something to service and see how it reacts. So I send some request (generated using WSDL) to address http://localhost:8733/ and get valid response. I used SoapUI for that. And there is no any breakpoints activity in VS! Message inspectors is not working. Breakpoint on service method hit, it shows that method really working without message inspector.

Also I tried attach behavior using this code to setup service (accordingly without specifing behavior in app.config):

ServiceHost myserviceHost = new ServiceHost(typeof(MyService), new Uri(Environment.bindAddress));            
myserviceHost.Open();

foreach (ServiceEndpoint endpoint in myserviceHost.Description.Endpoints)
{
    endpoint.Behaviors.Add(new LogMessageBehavior());
}

Console.WriteLine(myserviceHost.BaseAddresses[0]);
Console.ReadLine();

In this option we got this order of breakpoint hits:

1. public LogMessageBehavior() { }

That is it. And also no any inspector's activity on sending request to service.

So how can I get it work?

Peckham answered 28/11, 2012 at 3:41 Comment(6)
You need to enable and configure message logging.Applicant
@JohnSaunders I tried that. Please see my app.config. It writes corrupted log and even I don't know how to get human-readable messages with timestamps from it.Peckham
As to "corruption", you need to force the file to be flushed. Stopping the service will do that. For a service hosted in IIS, I just "touch" the web.config - open in Notepad, type space, type backspace, type Control-S. Service flushes logs and restarts.Applicant
How can I see message flow? I tried svctraceviewer and didn't observe something like that :)Peckham
Did you read the link I posted msdn.microsoft.com/en-us/library/ms730064.aspx?Applicant
Might be Fiddler can help youCalculus
D
1

Try opening the host after adding the behavior. It should work fine.

ServiceHost myserviceHost = new ServiceHost(typeof(MyService), new Uri(Environment.bindAddress));

foreach (ServiceEndpoint endpoint in myserviceHost.Description.Endpoints)
{
   endpoint.Behaviors.Add(new LogMessageBehavior());
}

myserviceHost.Open();

Console.WriteLine(myserviceHost.BaseAddresses[0]);
Console.ReadLine();
Daedalus answered 29/4, 2013 at 5:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.