Инспектор сообщений 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();