I am trying to implement a web service that accepts SOAP 1.2 over HTTP using WCF. Unfortunately I have to work with legacy clients that do not send an action
parameter as part of the HTTP header. This seems to be causing issues with WCF, which (by default at least) seems unable to route requests to the appropriate place without the action
.
I have created a binding based on BasicHttpBinding
but with the MessageVersion
set to MessageVersion.Soap12
, which I thought would remove the requirement to use WS-Addressing.
I then overloaded ApplyDispatchBehaviour
in IContractBehavior
to set DispatchRuntime.OperationSelector
to a custom implementation of IDispatchOperationSelector
that selects the correct operation based on the contents of the SOAP body (basically the approach used in this MSDN article)
By default this does not seem to work, and the SelectOperation
function is not called when a request is made.
However if I add in a dummy operation with an empty action to my contract, like so:
[OperationContract( Action = "" )]
void DoNothing();
then suddenly SelectOperation
begins to be called and my code works as expected. It seems like I've been unsuccessfully in making WCF no longer require the action header - I have just stopped the action header being used to directly map to operations. However, since the contract is generated from a .wsdl file it seems like an awful big hack to edit it in order to get things to work.
So my question is this: How can I go about accepting SOAP 1.2 requests without an action header using WCF? Unless I'm mistaken the SOAP 1.2 specification does not require an action header, so surely there is some way to implement this with WCF without resorting to hacking the contract?
I just managed to figure the answer to this question out today. It turns out that the EndpointDispatcher
being used had an ActionMessageFilter
as it's ContractFilter
and this was filtering out messages based on the action.
After I updated the ContractFilter
to a MatchAllMessageFilter
, then all messages were passed through to my IDispatchOperationSelector
where they could be selected based on the contents of the SOAP body.
The code I used to do this was in IContractBehavior.ApplyDispatchBehaviour
:
foreach(
var endpointDispatcher in
dispatchRuntime.ChannelDispatcher.Endpoints
)
{
endpointDispatcher.ContractFilter = new MatchAllMessageFilter();
}
I may update to use a more appropriate filter than MatchAllMessageFilter
in the future, but for now it is doing the job.