I have a simple classic ASP website that calls SOAP API using WCF. For debugging I need to log XML message contents manually into separate log files.
For example, the 12/23/18_34.txt file contains the XML request that was sent at 18:34 on 12/23. I have read through many articles that log WCF XML messages and found these 2 methods.
I could do log using the first method, but doing that I couldn't save the message contents to separate files with specific names. So I tried the second method, but it's not working and I can't find what's wrong.
As the current project is a classic ASP website and has no namespace, I am not sure how to set the value for the type attribute in the web.config
file.
I managed to add it by creating a separate dll file that has BehaviorExtensionElement
and copy it to the current project's Bin
folder.
<add name="logXmlBehavior" type="MessageLogger.MessageLoggerBehaviorExtensionElement, MessageLogger, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
public class MessageLogger : IClientMessageInspector
{
public void AfterReceiveReply(ref Message reply, object correlationState)
{
MessageBuffer buffer = reply.CreateBufferedCopy(Int32.MaxValue);
reply = buffer.CreateMessage();
var fileName = DateTime.Now.ToString("dd_HHmm");
System.IO.File.WriteAllText($"C:/Logs/Symmetry/{fileName}_response.txt", buffer.CreateMessage().ToString());
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue);
request = buffer.CreateMessage();
var fileName = DateTime.Now.ToString("dd_HHmm");
System.IO.File.WriteAllText($"C:/Logs/Symmetry/{fileName}_post.txt", buffer.CreateMessage().ToString());
return null;
}
}
This is my MessageLogger class, but it doesn't log anything. 🤕
How can I add the BehaviorExtensionElement
to a classic ASP website without a separate DLL?
And why is my current logger not working?
PS: The website is hosted using IIS.
Your code snippets seem that there is no problem. Please refer to my example.
MessageLogger class.
public class ClientMessageLogger : IClientMessageInspector
{
public void AfterReceiveReply(ref Message reply, object correlationState)
{
string displayText = $"the client has received the reply:\n{reply}\n";
Console.Write(displayText);
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
string displayText = $"the client send request message:\n{request}\n";
Console.WriteLine(displayText);
return null;
}
}
Endpoint Behavior to be applied on the client service endpoint.
public class AuthBehavior : BehaviorExtensionElement, IEndpointBehavior
{
public override Type BehaviorType => typeof(AuthBehavior);
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
ClientMessageLogger inspector = new ClientMessageLogger();
clientRuntime.ClientMessageInspectors.Add(inspector);
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
protected override object CreateBehavior()
{
return new AuthBehavior();
}
}
Then I register the endpoint behavior in the extension section and apply it on the automatically generated client service endpoint.
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService" />
</basicHttpBinding>
</bindings>
<client>
<!--apply it on the endpoint-->
<endpoint address="http://localhost:1300/" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IService" contract="ServiceReference1.IService"
name="BasicHttpBinding_IService" behaviorConfiguration="authBehavior" />
</client>
<behaviors>
<endpointBehaviors>
<behavior name="authBehavior">
<authbehavior />
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<!--like yours, namespace.class,assembly-->
<add name="authbehavior" type="Client3.AuthBehavior,Client3,Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
</system.serviceModel>
Eventually, the console application properly logs the message when sending a request to the server.
ServiceReference1.ServiceClient client = new ServiceReference1.ServiceClient();
//client.Endpoint.EndpointBehaviors.Add(new AuthBehavior());
try
{
Console.WriteLine(client.SayHello());
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Result.
Besides, I think the WCF trace also could complete this task logging the communication message. Just add the below configuration, check the mylogs.svclog
file in the bin folder.
<system.diagnostics>
<sources>
<source name="System.ServiceModel.MessageLogging">
<listeners>
<add type="System.Diagnostics.XmlWriterTraceListener" name="xmlLog" initializeData="myLogs.svclog"/>
</listeners>
</source>
</sources>
</system.diagnostics>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://10.157.13.70:1300/" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IService" contract="ServiceReference1.IService"
name="BasicHttpBinding_IService" />
</client>
<diagnostics>
<messageLogging logEntireMessage="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="false"/>
</diagnostics>
</system.serviceModel>
Feel free to let me know if there is anything I can help with.