Инспектор сообщений WCF не работает

Недавно я искал способ регистрировать любые запросы / ответы, которые обрабатывает моя служба WCF.

До этого у меня был плохой опыт с опцией трассировки. В настоящее время я еще не знаю, как получить реальные ответы и запросы от трассировки (я попробовал инструмент svctraceviewer, и он не получил что-то значимое для меня). И даже это, файл трассировки генерировался поврежденным (с некоторыми неожиданными символами в нем).

Я разобрался с технологией проверки сообщений примерно три или четыре дня назад. Я прочитал это руководство и внедрил инспектор сообщений на стороне клиента в другой мой проект. На самом деле я мог видеть любой запрос, отправленный моим клиентом wcf, и ответ службы другой стороны на этот запрос.

Я надеюсь, что это также легко сделать другую сторону регистрации (например, получать запросы на обслуживание от клиентов и ответы сервера для них). Но мне не холодно. Вот подробности:

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();
    }
}

Почти весь код заглушен с NotImplementedException, но я установил точки останова для каждого метода и свойства. Далее я расскажу, как они попали.

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>

Вот как устанавливается служба:

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

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

Класс обслуживания без каких-либо особых.

Итак, как же работает эта конструкция. Как я упоминал ранее, я устанавливаю точки останова в каждом методе и свойстве. И после того, как я начал отладку, мы получили хиты точек останова в следующем порядке:

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)

Хорошо, давайте попробуем отправить что-то в сервис и посмотрим, как это отреагирует. Поэтому я отправляю запрос (сгенерированный с использованием WSDL) по адресу http://localhost:8733/ и получите действительный ответ. Я использовал SoapUI для этого. И нет никаких остановок активности в VS! Сообщение инспекторов не работает. Точка останова при обращении к методу службы показывает, что метод действительно работает без инспектора сообщений.

Также я попытался подключить поведение, используя этот код для настройки службы (соответственно, без указания поведения в 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();

В этом варианте мы получили следующий порядок попаданий точки останова:

1. public LogMessageBehavior() { }

Вот и все. А также никакой деятельности инспектора по отправке запроса в сервис.

Так как я могу заставить это работать?

1 ответ

Попробуйте открыть хост после добавления поведения. Это должно работать нормально.

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();
Другие вопросы по тегам