Changing SOAP message data and namespaces with C#
WCF, you got to love it! I don't, but then again I don't get to always chose which technologies I can work with. I've recently come across a very peculiar and annoying problem while working against a particular web service. I was able to hit the endpoints using SOAP UI but all calls from code were failing miserably. The project required importing a third party WSDL in order to generate the appropriate proxy classes etc. The WSDL had to be added as a Service Refernce instead of Web Reference as the exteranl API did not expose a Web Services Metadata Exchange.
With the proxy in place I assumed that everything should work as expected but this could not be far from truth. In the end, I fired up Fiddler and started comparing the SOAP UI messages to the C# ones. The difference in the payload was quite significant, mainly around the namespace declaration. The API expected all namespaces to be declared at the top, while the proxy was declaring the namespaces against each individual element.
It took quite a bit of google/Bing(ing) to realize that there is no way to change the <envelop>
format without performing some serious workarounds. Also, since I had no access to the server running the API, there was no way to use handlers etc to change the message format. And finally, I was not allowed to touch or alter the auto-generated proxy from WSDL! Challenge accepted
The Solution
In the end, I came up with a perfectly satisfactory solution that met all the above requirements and didn't look like a dirty, aweful hack that you try to forget as soon as it goes into production. The solution provided below allows you to change any part of the message on the client side before sending it to the server. This way, you have full control of the generated SOAP XML.
First, we need to to implement a custom IClientMessageInspector implementation. This was my way in and I could access the full SOAP message and change it as needed.
Next, we need to create a custom implementation of a WCF IEndpointBehavior which is a WCF extensibility feature. You can find more details about this interface here. Within the implementation, we will make use of our CustomMessageInspector that we created above. This will allow us to automatically intercept the SOAP message prior to sending it to the API.
Testing our new solution
If you follow some form of TDD or any other form of unit testing, then you can quickly put a test together to validate that your implementation works.
The important code in the unit test is shown below:
var testservice = new CustomClient(endpointname, endpoint);
var requestInterceptor = new CustomInspectorBehavior();
testservice.Endpoint.Behaviors.Add(requestInterceptor);
We instantiate a CustomInspectorBehavior
and attach it to the Service (WSDL proxy class wrapper).
And simply like this, you can intercept and change any SOAP message without messing with your proxy classes. I hope this helps you in some way.