views:

238

answers:

1

I'm using WCF to implement a web service. This web service requires a 'ping' feature as a health monitor for each service. This functionality has been implemented using IDispatchMessageInspector and is configured for each endpoint of a service. This is due to a business requirement for the 'ping' to be as near the actual service code as possible. At the same time, I did not want to tie it to each service implementation's code and IDispatchMessageInspector seems to be a good fit.

The service uses a Request-Reply MEP. Each request message contains an element that specifies what processing is required. The service will then use this value to determine how to process the data in the message. The same element is used to define a request message as a 'heartbeat' check.

The 'ping' message inspector will pre-process a request message in the AfterReceiveRequest() method and if it determines the request is a 'heartbeat', it will then generate the correct response and pass that on to the BeforeSendReply() method via a correlation object returned from AfterReceiveRequest(). The request message parameter of AfterReceiveRequest(), which is by reference, is then set to null to prevent the message from being processed by the service implementation code.

The technique of setting request message to null was found in a web site or blog which I can't remember nor find the URL for. This technique works great on it's own and I can prevent service implementation code from being executed if it's a 'heartbeat' request.

Unfortunately, setting the request message to null in a message inspector will cause the WCF runtime to always throw a NullReferenceException. From the stack trace, I gather the runtime will still pass the message object (which will be null after going through 'Ping' message inspector) to the dispatcher and when the dispatcher tries to deserialise a null message object, causes the NullReferenceException.

However, my system also implements IErrorHandler to catch any unhandled exceptions in the service and log it. This means every successful 'heartbeat' request will generate a log entry for the NullReferenceException and the 'heartbeat' could be as frequent as every minute.

The Question :

What can I do to prevent logging of 'useless' NullReferenceException thrown when 'Ping' prevents service implementation code from running by setting request to null.

Many thanks in advance.
~hg

A: 

Not the most graceful solution but potential workarounds (that i've not tested), but where you detect your ping calls in the inspector code, could you not throw your own custom exception type i.e. PingRequestException, and handle this when it returns to the client? Would that avoid you hitting the WCF Runtime code, thus avoiding the logging of unhandled exceptions.

Otherwise you could try to use a base service, inherited by all of your services (the other side of the wcf runtime code) that detects and handles ping requests in the constructor before hitting the actual service code.

Tanner
Thanks Tanner, unfortunately there are further complications. Option two is not applicable as there are other considerations that prevent putting ping code in a base service class. Option one may work as I can then filter out that exception from being logged. However, the system may receive 'Ping' as often as once a minute or even more frequent. Won't throwing that many exceptions impact performance severely?
hg
Tanner
Unfortunately, I can't remove the endpoint coupling as business requirements prevent it. Essentially, ping functionality is required in every business operation i.e. no change in the URL of the web service. As I understand it, that pretty much limits me to either an endpoint specific extension or putting it into the service implementation itself in every operation's code. Would have been nice to have a 'base' service implementation containing ping but I can't change now. I'll give the PingRequestException method a try.
hg
Thanks Tanner, the custom exception solution works fine. It actually killed two birds with one stone as the solution resolved WCF runtime throwing NullReferenceException due to null request message set by message inspetors. I created a new message inspector which will detect if the request message is null and throw custom exception which is excluded in the unhandled exceptions handler. Only requirement is to have a configuration document to specify the null reference handler MUST be last message inspector configured.
hg