2012-11-28 65 views
1

最近,我正在探索一些方法来记录我的WCF服务处理的任何请求/响应。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) 

OK,让我们试着送东西到服务,看看它是如何反应。所以我发送一些请求(使用WSDL生成)来解决http://localhost:8733/并获得有效的响应。我为此使用了SoapUI。 VS中没有任何断点活动!信息检查员不工作。服务方法命中的断点,它显示该方法确实在没有消息检查器的情况下工作。

我也试着连接使用此代码设置服务行为(没有相应的specifing行为的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

您需要启用并配置[消息记录](http://msdn.microsoft.com/zh-cn/library/ms730064.aspx)。 –

+0

@JohnSaunders我试过了。请看我的app.config。它写入损坏的日志,甚至我不知道如何从它获取带有时间戳的人类可读信息。 – kseen

+0

至于“腐败”,你需要强制文件被刷新。停止服务将做到这一点。对于托管在IIS中的服务,我只是“触摸”网页。config - 在记事本中打开,键入空格,键入退格键,键入Control-S。服务会刷新日志并重新启动。 –

回答

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