calculate number of calls made to WCF service - wcf

I have a service contract with 5 different operation contract and hosted in IIS.
Now suppose I want to charge customer (client) based on number of calls made to our WCF service (hitting different-different operation contract ).
How is it possible to do so in WCF, what settings we need to do in WCF service side?

WCF offers extensibility points; wherein WCF extension facilitates to plug in any custom code at different places in WCF Pipeline.
For your need, you can use the MessageInspector to inspect the message and increment a counter for the method call. MessageInspector allows to intercept and examines the messages coming in or going out of the service layer infrastructure. Message inspector can be applied on both the client and Server side.
1.In this specific scenario, you need to use the Server-side inspector by implementing IDispatchMessageInspector
public class MessageCounterMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
// Increment Counter in thread safe way
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
}
}
Then implement the IServiceBehavior interface.
[AttributeUsage(AttributeTargets.Class)]
public class CounterBehavior : Attribute, IServiceBehavior
{
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
for (int i = 0; i < serviceHostBase.ChannelDispatchers.Count; i++)
{
ChannelDispatcher channelDispatcher = serviceHostBase.ChannelDispatchers[i] as ChannelDispatcher;
if (channelDispatcher != null)
{
foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints)
{
MessageCounterMessageInspector inspector = new MessageCounterMessageInspector ();
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
}
}
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
}
Apply the attribute in step2 to your service class.
[CounterBehavior]
public class YourService : IYourService
{
}
Note : For Counter, you may use the Static variable to keep a track of count of method, just ensure that the increment in thread safe.

You can either call some standard method from each of the service implementation methods (perhaps using CallerMemberNameAttribute to save yourself some typing)
or you can inject "accounting" methods by using WCF custom behaviors

Related

How to invoke an IApplicationService into a WCF SOAP services in abp Boilerplate?

I developed a MVC application using abp boilerplate and now I have the necessity to expose some services via WFC/SOAP.
The idea is to create a WFC Service, inject the required IApplicationService and use it.
Something like:
// this code does not work
public class MyFirstService : IMyFirstService, ITransientDependency {
private readonly ICourseAppService _courseAppService;
// Injection here does not work!
public MyFirstService(ICourseAppService courseAppService) {
_courseAppService = courseAppService;
}
public CourseDto GetData(int id) {
return _courseAppService.Get(id);
}
}
But this code does not work. :-(
The first error I have is from WCF saying the Service does not have a default constructor without parameters. So I am on the wrong way.
How can I inject the service into the SOAP service?
The answer https://stackoverflow.com/a/46048289/752004 did not help me.
WCF uses Reflection to create service instance, so if your service has no constructor without parameters , wcf will fail to create the service instance which is why wcf shows the error.
It is not easy to integrate injection framework with wcf.
You should customize instance provider(which provides wcf service instance).
https://blogs.msdn.microsoft.com/carlosfigueira/2011/05/31/wcf-extensibility-iinstanceprovider/
In your customized instance provider , you could provide your injected service instance in the method GetInstance.
Then you should make wcf use your own instance provider using service behavior.
For example
public class MyServiceAttribute : Attribute, IServiceBehavior
{
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher item in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher item1 in item.Endpoints)
{
item1.DispatchRuntime.InstanceProvider = new MyInstanceProvider(); // apply customized instanceProvider
}
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
}
Then you should customize a ServiceHost to apply the service behavior.
Like
public class MyUnityServiceHost : ServiceHost
{
protected MyUnityServiceHost()
{
}
protected override void OnOpening()
{
base.OnOpening();
if (this.Description.Behaviors.Find<MyServiceAttribute >() == null)
{
this.Description.Behaviors.Add(new MyServiceAttribute ());//add your behavior
}
}
}
At last, you should customize HostFactory to create your customized servicehost.
https://blogs.msdn.microsoft.com/carlosfigueira/2011/06/13/wcf-extensibility-servicehostfactory/
You could refer to the similar discussion below.
Injecting data to a WCF service
Abp uses the Castle Windsor, so following the suggestions from this answer and this article I found the solution.
Once imported the nuget package Castle.WcfIntegrationFacility, I created a new WCF library and in it I created a AbbModule class where I registered MyService (defined in pt. 3):
[DependsOn(typeof(BookingCoreModule), typeof(BookingApplicationModule))]
public class BookingSoapModule : AbpModule {
public override void Initialize() {
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
IocManager.IocContainer.AddFacility<WcfFacility>().Register(
Component
.For<IMyService>()
.ImplementedBy<MyService>()
.Named("MyService")
);
}
}
Then I created my IMyService interface (note that it extends ITransientDependency):
[ServiceContract]
public interface IMyService : ITransientDependency {
[OperationContract]
CourseDto GetCourse(int courseId);
}
Finally I implemented the interface with a constructor using injection:
public class MyService : IMySecondService {
private readonly ICourseAppService _courseAppService;
public IAbpSession AbpSession { get; set; }
public ILogger Logger { get; set; }
public MyService(ICourseAppService courseAppService) {
AbpSession = NullAbpSession.Instance;
Logger = NullLogger.Instance;
_courseAppService = courseAppService;
}
public CourseDto GetCourse(int courseId) {
AsyncHelper.RunSync(async () => {
var course = await _courseAppService.Get(courseId);
return course;
});
}
}

Custom WCF service factory and hooking all calls

I would to intercept all post request to a custom WCF service (.net 3.5 SP1) in order to validate the presence of a specific header.
What I tried so far:
public class ServiceFactory : WebServiceHostFactory
{
protected override System.ServiceModel.ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
var result = base.CreateServiceHost(serviceType, baseAddresses);
result.Opened += result_Opened;
return result;
}
private void result_Opened(object sender, EventArgs e)
{
var ctx = HttpContext.Current;
var request = ctx.Request;
if (request.HttpMethod == "POST")
{
// Validate if the request contains my header
if(request.Headers["MyHeader"] != "42")
throw new VeryBadThingsException("boom");
}
}
}
I also set up my svc files to use this factory.
This is sometimes working. Actually, not all my web services calls are hooked by the open event handler. The web service actual implementation is reached, so I suppose the problem is not the web service itself.
What should I do to correctly hook all incoming requests to my service?
PS: to descbribe a bit more my context, the service is hosted by SharePoint 2010. That means I can't change the web.config file (technically it's possible, but it's a pain to deploy and maintain).
And I acutally inherits the class Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHostFactory
You should implement the IDispatchMessageInspector on the service side for this. The message instance passed to you in the AfterReceiveRequest method has a Headers property where you can check for your required headers.
Your current solution doesn't work for every call because it is only getting called when a new service host is opened. Once instantiated (and opened), that service host instance is servicing subsequent calls. But, because it is already opened, your code is not getting called on these subsequent calls.
You need to extend the WCF pipeline by adding a message inspector. The message inspector of the client will be responsible for adding the header and the message inspector of the server will be responsible for validating if the header exists.
Good practice: if you want to create custom headers, specify a custom namespace to ease lookup.
public static class WCFSOAPNamespaces
{
private const string root = "http://www.schemas.productname.com/";
public const string Headers = root + "headers/";
}
Server
The IDispatchMessageInspector handles all incoming messages to the server. This is the place where you will check for the existence of the header on the server.
public class DispatchMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
const string headerName = "nameOfTheHeader";
var someHeaderData = request.Headers.GetHeader<string>(headerName, WCFSOAPNamespaces.Headers);
//someHeaderData is the content that you want to check for every request. Attention: it throws System.ServiceModel.MessageHeaderException if the header doesn't exist
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState) { }
}
Client
The IClientMessageInspector handles messages on the client. If you need to add custom headers to the message, here is the place. If you do not need to add custom header, you can jump this first piece of code.
public class ClientMessageInspector : IClientMessageInspector
{
public void AfterReceiveReply(ref Message reply, object correlationState) { }
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
const string headerName = "nameOfTheHeader";
string headerContent = ""; //fill this variable with the content
var header = new MessageHeader<string>(headerContent ?? string.Empty);
var untyped = header.GetUntypedHeader(headerName, WCFSOAPNamespaces.Headers);
request.Headers.Add(untyped);
return null;
}
}
Both (client and server)
Even if you do not need a message inspector on the Client, you still need this configuration to add message inspection to your server-side application. More specifically, we need an EndpointBehavior to handle the MessageInspector. Then, we need to set the services endpoits to use this custom endpoint behavior.
In this example, I put the 2 inspectors in the same behavior, but you can create separate behaviors if you need.
public class EndpointBehavior : BehaviorExtensionElement, IEndpointBehavior
{
public EndpointBehavior() { }
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(new ClientMessageInspector());
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new DispatchMessageInspector());
}
public void Validate(ServiceEndpoint endpoint) { }
public override Type BehaviorType
{
get { return this.GetType(); }
}
protected override object CreateBehavior()
{
return new EndpointBehavior();
}
}
Then, set your Endpoint to use this behavior.
Programmatically
...
ServiceEndpoint endpoint;
...
endpoint.Behaviors.Add(new EndpointBehavior());
Config
...
<services>
<service name="...">
<endpoint address="..." binding="..." contract="..." behaviorConfiguration="endpointBehaviorName" />
</service>
...
<behaviors>
...
<endpointBehaviors>
<behavior name="endpointBehaviorName">
<customEndpointBehavior />
</behavior>
</endpointBehaviors>
</behaviors>
...
<extensions>
<behaviorExtensions>
<add name="customEndpointBehavior" type="FullNamespace.EndpointBehavior , AssemblyName" />
</behaviorExtensions>
</extensions>
From now on, all the requests will pass through this point.
Hope it helps.
Ok, I manage to swim between all objects, with the help of the code project article Add Custom Message Header in WCF 4 Calls.
Especially, it helped me to figure out how to properly attach a ServiceBehavior through code, using attributes.
I finally have this:
internal class ValidateSPFormDigestAttribute : Attribute, IServiceBehavior
{
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase host)
{
foreach (ChannelDispatcher cDispatcher in host.ChannelDispatchers)
{
foreach (EndpointDispatcher eDispatcher in cDispatcher.Endpoints)
{
eDispatcher.DispatchRuntime.MessageInspectors.Add(new ValidateSPFormDigestInspector());
}
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
}
internal class ValidateSPFormDigestInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
if (!SPUtility.ValidateFormDigest())
{
throw new FaultException(new FaultReason("Invalid form digest token"));
}
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
}
}
And I attach my custom behavior on the service directly:
[BasicHttpBindingServiceMetadataExchangeEndpoint]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
[ValidateSPFormDigest]
public class MyCustomService: IWidgetAdminService
The immediate benefits, is that I no more require creating a custom web service factory!

Using the Windsor NHibernateFacility in a Wcf Service with a custom service behavior for creating transactions instead of the Transaction attribute

I am trying to use the Windsor NHibernate Facility for the first time in a Wcf service and replace the current manual registration of NHibernate so that there can be a consistent approach across all services.
Current working approach
Previously I had been registering the NHibernate components manually.
container.Register(
Component.For<ISessionFactory>().UsingFactoryMethod(() => CreateMappings("SomeConnectionString").BuildSessionFactory()));
container.Register(
Component.For<ISession>().LifeStyle.PerWcfOperation().UsingFactoryMethod(OpenSession));
I was then using a custom service behavior to create and complete a transaction scope for each operation.
public class TransactionBehavior : IServiceBehavior
{
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (var cdb in serviceHostBase.ChannelDispatchers)
{
var channelDispatcher = cdb as ChannelDispatcher;
if (null == channelDispatcher) continue;
foreach (var endpointDispatcher in channelDispatcher.Endpoints)
{
foreach (var dispatchOperation in endpointDispatcher.DispatchRuntime.Operations)
{
dispatchOperation.CallContextInitializers.Add(new TransactionContext());
}
}
}
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { }
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { }
}
public class TransactionContext : ICallContextInitializer
{
private TransactionScope transaction;
public Object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message)
{
transaction = new TransactionScope();
return null;
}
public void AfterInvoke(Object correlationState)
{
if(transaction != null)
{
transaction.Complete();
transaction.Dispose();
}
}
}
Integration of the NHibernate Facility
I have downloaded the 0.3.1.2001 artifacts and using the resources below I have tried to plug in the facility and remove any manual wire up to NHibernate. However I do not want to decorate services and methods with the Transactional and Transaction attributes. The following is my current wire up.
container.Register(Component.For<INHibernateInstaller>().ImplementedBy<MyNHibernateInstaller>();
container.AddFacility<AutoTxFacility>();
container.AddFacility<NHibernateFacility>();
public class MyNHibernateInstaller : INHibernateInstaller
{
public Maybe<IInterceptor> Interceptor { get { return Maybe.None<IInterceptor>(); } }
public bool IsDefault { get { return true; } }
public string SessionFactoryKey { get { return "sf.default"; } }
public FluentConfiguration BuildFluent()
{
return Fluently
.Configure()
.Database(MsSqlConfiguration
.MsSql2005.ConnectionString("SomeConnectionString") )
.Mappings( m => m.FluentMappings
.AddFromAssemblyOf<TypeFromEntityAssembly>() );
}
public void Registered(ISessionFactory factory)
{
}
}
Whenever I call one of the service endpoints the service fails with the following exception:
No transaction in context when trying to instantiate model
'NHibernate.ISession' for resolve type
'Juice.iCheque.eMoneySystem.Settlement.ISettlementService'. If you
have verified that your call stack contains a method with the
[Transaction] attribute, then also make sure that you have registered
the AutoTx Facility.
The question is how do I use the NHibernateFacility with my current implementation and not use the Transaction attribute.
Resources
http://richarddingwall.name/2010/08/17/one-nhibernate-session-per-wcf-operation-the-easy-way/
https://github.com/haf/Castle.Facilities.NHibernate/wiki/NHibernate-Facility---Quick-Start
Firstly you should know that Henrik Feldt's Castle Transactions and AutoTx Facility interpretations require [Transaction] attribute usage (as I have discussed with Mr.Feldt in Castle Users mailing lists some time ago).
If you want to get rid of the [Transaction] attribute from your service classes (to achive POCO) but continue to use NH and WCF per call session scenario you should:
Keep your IServiceBehaviour implementation but inject an IDispatchMessageInspector interface at the constructor, and assign it to a class global IDispatchMessageInspector property.
At ApplyDispatchBehavior method foreach ChannelDispatcher in serviceHostBase, loop endpoints and add injected DispatchMessageInspector instance:
foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
{
foreach (var endpoint in channelDispatcher.Endpoints)
{
endpoint.DispatchRuntime.MessageInspectors.Add(this.dispatchMessageInspector);
}
}
Create a class implementing IDispatchMessageInspector (the one that would be injected at the previous item). Lets call this class NHWcfIntegrationMessageInspector.
Inject ISessionFactory to NHWcfIntegrationMessageInspector, and set it to local property.
In AfterRecieveRequest method create an NH session object with ISessionFactory.Open(), begin transaction and bind that ISession to CurrentSessionContext
In BeforeSendReply method unbind injected SessionFactory from CurrentSessionContext, which gives you the actual session object. Check transaction is active from session's Transaction property and if active Commit() it. Then Dispose() session.
Dont use INHibernateInstaller. Instead use IWindsorInstaller and implement it with MyHibernateInstaller. At registration block, register both your IServiceBehavior implementation and your new IDispatchMessageInspector implementation to container.
Also register ISessionFactory in same installer and give FNH configuration method as a factory method but give a builded ISessionFactory. But at your FNH config before building ISessionFactory from fluentconfiguration object call:
fluentConfiguration.CurrentSessionContext<WcfOperationSessionContext>();
Ta DAAA!
After completing these steps, you dont have to hold references to Haf's libraries anymore. Its pure Castle.Core, Castle.Windsor, NH/FNH.
Any questions? ;)
(sorry for not posting the complete code but just description, I am under contract obligation)

Specify a Singleton service in a WCF self hosted service

I am writing an application that exposes a service via WCF. The service is self-hosted (console app) and needs to use a Singleton instance. I am trying to figure out how to specify singleton in the service configuration without using attributes on the service implementation. Is it possible to specify singleton in code without an attribute?
Thanks,
Erick
You can pass instance of the service to the ServiceHost constructor instead of passing a type. In such case your passed instance will be used as singleton.
Edit:
My former solution doesn't work. Providing instance to ServiceHost constructor still demands ServiceBehaviorAttribute with InstanceContextMode.Single. But this one should work:
var host = new ServiceHost(typeof(Service));
var behavior = host.Description.Behaviors.Find<ServiceBehaviorAttribute>();
behavior.InstanceContextMode = InstanceContextMode.Single;
host.Open();
ServiceBehaviorAttribute is included even if you don't specify it so you just need to get it and change default value.
If you want to move this into web.config or app.config, you could do so with a custom BehaviorExtensionElement and IServiceBehavior:
The IServiceBehavior will actually parse the value from config into the enum and set it (following #Ladislav's answer):
public class InstanceContextServiceBehavior : IServiceBehavior
{
InstanceContextMode _contextMode = default(InstanceContextMode);
public InstanceContextServiceBehavior(string contextMode)
{
if (!string.IsNullOrWhiteSpace(contextMode))
{
InstanceContextMode mode;
if (Enum.TryParse(contextMode, true, out mode))
{
_contextMode = mode;
}
else
{
throw new ArgumentException($"'{contextMode}' Could not be parsed as a valid InstanceContextMode; allowed values are 'PerSession', 'PerCall', 'Single'", "contextMode");
}
}
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
var behavior = serviceDescription.Behaviors.Find<ServiceBehaviorAttribute>();
behavior.InstanceContextMode = _contextMode;
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
return;
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
return;
}
}
The extension element allows you to pull it from config and pass it to the IServiceBehavior:
public class InstanceContextExtensionElement : BehaviorExtensionElement
{
public override Type BehaviorType
{
get
{
return typeof(InstanceContextServiceBehavior);
}
}
protected override object CreateBehavior()
{
return new InstanceContextServiceBehavior(ContextMode);
}
const object contextMode = null;
[ConfigurationProperty(nameof(contextMode))]
public string ContextMode
{
get
{
return (string)base[nameof(contextMode)];
}
set
{
base[nameof(contextMode)] = value;
}
}
}
And you can then register it in your config and use it:
<extensions>
<behaviorExtensions>
<add name="instanceContext" type="FULLY QUALFIED NAME TO CLASS"/>
</behaviorExtensions>
</extensions>
...
<serviceBehaviors>
<behavior name="Default">
<instanceContext contextMode="Single"/>

WCF, Unable to extract httpheader when sending messages as <security mode="Message">

Im relativly new to WCF and/but "seem" to have got most things up and working.
I have the following IEndpointBehavior and IClientMessageInspector that I want to append when calling the service. It appends a token (HTTPHeader) that I want to check serverside (IIS)
public class AuthenticationTokenEndpointBehavior : IEndpointBehavior
{
#region Member variables
public class AuthenticationTokenMessageInspector : IClientMessageInspector
{
public void AfterReceiveReply(ref Message reply, object correlationState)
{
//throw new NotImplementedException();
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
string token = AuthenticationTokenManager.CreateToken();
HttpRequestMessageProperty httpRequestMessage;
object httpRequestMessageObject;
if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out httpRequestMessageObject))
{
httpRequestMessage = httpRequestMessageObject as HttpRequestMessageProperty;
}
else
{
httpRequestMessage = new HttpRequestMessageProperty();
request.Properties.Add(HttpRequestMessageProperty.Name, httpRequestMessage);
}
httpRequestMessage.Headers[AuthenticationTokenManager.AUTHENTICATION_TOKEN_NAME] = token;
return null;
}
#endregion
#region Methods
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
//throw new NotImplementedException();
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
AuthenticationTokenMessageInspector inspector = new AuthenticationTokenMessageInspector();
clientRuntime.MessageInspectors.Add(inspector);
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
//throw new NotImplementedException();
}
public void Validate(ServiceEndpoint endpoint)
{
//throw new NotImplementedException();
}
#endregion
}
I have inherited and overriden the clientproxys CreateChannel, in which I append my IEndpointBehavior.
protected override ITheService CreateChannel()
{
this.Endpoint.Behaviors.Add(new AuthenticationTokenEndpointBehavior());
return base.CreateChannel();
}
This works very well for most of my bindings except when using <security mode="Message">. The headers are not sent to the server. Ive have googled abit but not found any information about this issue.
UPDATE 1: To clarify, the IClientMessageInspector.BeforeSendRequest IS called but no headers appears on the serverside.
UPDATE 2: I tried add a SoapHeader (MessageHeader) instead but no luck. Is there some sort of security "handshake" involved before the first request??
Responding to your Update 2: depending on the exact configuration of your binding there may very well be a preliminary exchange of SOAP messages carrying WS-Trust security token request/response, before your application messages are exchanged. For example the default configuration of message security for the wsHttpBinding will do this.
I solved this using IDispatchMessageInspector at the serviceend for WCF calls. Not the easy/quick way, with the HTTPModule validation, I was looking for. But it turned out ok. #Chris Dickson, thanks for your time!