Reputation: 19591
I'm trying to log the requests & responses to & from my WCF service. What I have done till now is:
public class OutputMessageInspector : IDispatchMessageInspector
{
int lastLogId;
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
// Parse request & read required information
// Insert request data into log tables
// Set lastLogId to the id created above
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
// Parse reply
// Using lastLogId update the response column in database table
}
}
Everything is working fine but I have one concern:
AfterReceiveRequest
and BeforeSendReply
has to be working in a sync so that BeforeSendReply
will update correct record. The case I have in mind is of Service getting called from multiple clients at the same time, question:
lastLogId
get messed up and shuffled among multiple
requests & responses?BeforeSendReply
will work
fine with multiple clients calling service at the same time? If yes
then please give me an explanation to assure my mind if no then
please provide a better solution to this.Upvotes: 1
Views: 3056
Reputation: 5801
I agree with @Schneiders solution to use WCF logging for your requirements.
However to answer your question:
Would this logging specially update at BeforeSendReply will work fine with multiple clients calling service at the same time?
No it will not. Instances of the IDispatchMessageInspector
are shared across calls.
Instead of using member properties, call specific data is supported through the correlationState
on IDispatchMessageInspector
. Whatever object AfterReceiveRequest()
returns will be passed as the correlationState
to BeforeSendReply()
.
In other words something like this should work:
public class OutputMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
// Parse request & read required information
// Insert request data into log tables
// Set lastLogId to the id created above
return lastLogId
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
// Parse reply
int lastLogId = (int)correlationState;
}
}
Upvotes: 5
Reputation: 13501
Firstly: WCF has the built in ability to log the requests & responses so it might be worth investigating that before you roll your own solution.
As to your problem, normally you are applying the IDispatchMessageInspector as a service or endpoint behaviour, hooking the ApplyDispatchBehavior. In there you are probably creating a new OutputMessageInspector and adding it to the DispatchRuntime.MessageInspectors collection.
Behaviors only get applied once when the service or endpoint is created, so you can infer from that there is only one DispatchRuntime and you are only creating one MessageInspector so it's going to be shared across all requests/threads.
In which case your OutputMessageInspector needs to be "thread safe". If you hold state in there you are going to need to synchronize access to it so that it doesn't get scrambled.
Upvotes: 1