In my WCF project I need to use custom headers in responses so I implemented IDispatchMessageInspector. Honestly all works pretty fine, but I'm disturbing about one little thing.
The thing is that both BeforeSendReply and AfterReceiveRequest fires even when I just open my .svc as page, or load service into WCF Test Client.
So, the first question: Is that behavior normal? Are there some ways to handle that declaratively (maybe some web.config trick)?
Currently I use next code:
public void BeforeSendReply(ref Message reply, object correlationState)
{
if (reply.Properties.Any(x => x.Key == "httpResponse"))
return;
MessageHeader header = MessageHeader.CreateHeader("Success", "NS", !reply.IsFault);
reply.Headers.Add(header);
}
So now I handle all calls which aren't service calls by using that:
if (reply.Properties.Any(x => x.Key == "httpResponse"))
return;
But I'm pretty sure there some other and better way to handle that problem.
So my main question: please suggest me a better way to handle described situation.
Thanks in advance!
UPDATE 1
My system.serviceModel section
<system.serviceModel>
<services>
<service behaviorConfiguration="someBehavior" name="serviceName">
<endpoint address="" binding="basicHttpBinding" contract="my contract" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="someBehavior">
<serviceMetadata httpGetEnabled="true" httpGetUrl=""/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<exceptionInspector/>
</behavior>
</serviceBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="exceptionInspector" type="class which implements BehaviorExtensionElement" />
</behaviorExtensions>
</extensions>
</system.serviceModel>
UPDATE 2 (ACCEPTED SOLUTION)
I spent some time investigation source of problem and finally I've found acceptable for me solution.
So what have I found:
First of all Message
is a abstract class. So BeforeSendReply
each time receive defferent types of concrete messages.
Most used are:
1) System.ServiceModel.Description.ServiceMetadataExtension.HttpGetImpl.MetadataOnHelpPageMessage
- means that client opens svc as page. Result = well known html formatted page with common information about svc service. For this type reply.Version.Envelope
is EnvelopeVersion.None
.
2) Get metadata request. This is slightly tricky part and it depends if we use MEX or not.
So if we use MEX then request performs to .svc/mex endpoint and its Message type will be System.ServiceModel.Dispatcher.OperationFormatter.OperationFormatterMessage
with reply.Version.Envelope
equal to EnvelopeVersion.Soap12
.
In case if we don't use MEX then client performs few requests for obtaining wsdl data. Message type will be XMLSchemaMessage
.
3) Execute web method request. This only useful for me type of requests. It is System.ServiceModel.Dispatcher.OperationFormatter.OperationFormatterMessage
and has reply.Version.Envelope
equal to EnvelopeVersion.Soap11
.
I'm using basicHttpBinding so SOAP version is 1.1. So my final code should just check is reply has SOAP envelope and check version of it. In case if envelope exists and has version 1.1 then we may be pretty sure that we have web method call and custom header might be added:
public void BeforeSendReply(ref Message reply, object correlationState)
{
if(reply.Version.Envelope == EnvelopeVersion.Soap11)
{
MessageHeader header = MessageHeader.CreateHeader("Success", "NS", !reply.IsFault);
reply.Headers.Add(header);
}
}