I need to apply a custom message formatter to all operations within a service.
Rather than apply an OperationBehavior manually to all the operations, I am attempting to loop through all operations from within a ServiceBehavior thusly (the details of my serializer aren’t important, just that it implements IDispatchMessageFormatter):
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase) {
foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers) {
foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints.Where(e => !e.IsSystemEndpoint)) {
foreach (DispatchOperation dispatchOperation in endpointDispatcher.DispatchRuntime.Operations) {
LoggedOperationSerializer serializer = new LoggedOperationSerializer(dispatchOperation.Formatter);
dispatchOperation.Formatter = serializer;
}
}
}
}
The serializer seems to get set fine, with no errors. However, the DeserializeRequest method on LoggedOperationSerializer is never hit when I set a breakpoint and debug.
If instead I apply the formatter inside an OperationBehavior like this:
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) {
LoggedOperationSerializer serializer = new LoggedOperationSerializer(dispatchOperation.Formatter);
dispatchOperation.Formatter = serializer;
}
then the DeserializeRequest method is hit as expected.
If I apply both a ServiceBehvior and an OperationBehavior as shown and attach a debugger, as expected, the first code block shown is hit first, iterating through all operations on the service, and the formatter is set. However, by the time that the ApplyDispatchBehavior for the OperationBehavior is hit, the formatter set above has “fallen off”, and has been replaced by the default CompositeDispatchFormatter.
I really don’t want to have to apply an OperationBehavior manually to all operations to get this to work… any ideas on why what might be happening?
This is using WebHttpBinding in case that is at all relevant, I don’t know why it would be though.
If you’re using
WebHttpBinding, I’m assuming you’re also using theWebHttpBehaviorin your endpoint. If so, then theWebHttpBehavioris overriding the formatter you added in your service behavior.For all behaviors in WCF, when
ApplyDispatchBehavioris called, it’s called in the following order: Service behaviors, contract behaviors, endpoint behaviors, operation behaviors (which explains why when you use an operation behavior it works). The WebHttpBehavior will set its formatter to deal with things such understanding JSON inputs, mapping to URI templates, etc.If you don’t want to add operation behaviors to all the operations in your services, you can either use an endpoint behavior, added after the WebHttpBehavior in your endpoint, or an endpoint derived from
WebHttpBehaviorwhere you only overrideApplyDispatchBehavior, first calling the base implementation, then you loop through all the operations in the contract to set yourLoggedOperationSerializer.