最近,我正在探索一些方法来记录我的WCF服务处理的任何请求/响应。
在此之前,我对跟踪选项有一些不好的经验。如今,我还不知道如何从跟踪中获得实际的响应和请求(我尝试过svctraceviewer工具并且它没有为我带来任何有意义的东西)。即便如此,跟踪文件也会被破坏(其中包含一些不可思议的字符)。
我在三四天前发现了消息检查员的技术。我读了this manual并在我的其他项目中实现了客户端消息检查器。实际上,我可以看到我的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() { }
就是这样。并且没有任何检查员在发送服务请求时的活动。
那我怎么能让它发挥作用呢?
答案 0 :(得分:0)
添加行为后尝试打开主机。它应该工作正常。
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();