C# – How to get access to SOAP response

csoapweb serviceswse2.0xml

(If anything here needs clarification/ more detail please let me know.)

I have an application (C#, 2.* framework) that interfaces with a third-party webservice using SOAP. I used thinktecture's WSCF add-in against a supplied WSDL to create the client-side implementation. For reasons beyond my control the SOAP message exchange uses WSE2.0 for security (the thinctecture implementation had to be modified to include the WSE2.0 reference). In addition to the 'normal' data package I attach a stored X509 cert and a binary security token from a previous call to a different web service. We are using SSL encryption of some sort – I don't know the details.

All the necessary serialization/deserialization is contained in the web service client – meaning when control is returned to me after calling the client the entire XML string contained in the SOAP response is not available to me – just the deserialized components. Don't get me wrong – I think that's good because it means I don't have to do it myself.

However, in order for me to have something worth storing/archiving I am having to re-serialize the data at the root element. This seems like a waste of resources since my result was in the SOAP response.

Now for my question:
How can I get access to a 'clear' version of the SOAP response so that I don't have to re-serialize everything for storage/archiving?

Edit- My application is a 'formless' windows app running as a network service – triggered by a WebsphereMQ client trigger monitor. I don't think ASP.NET solutions will apply.

Edit – Since the consensus so far is that it doesn't matter whether my app is ASP.NET or not then I will give CodeMelt's (and by extension Chris's) solution a shot.

Best Answer

You can utilize SoapExtension from existing WSE2.0 framework to intercept the responses from the server.

public class MyClientSOAPExtension : SoapExtension

     Stream oldStream;
     Stream newStream;

     // Save the Stream representing the SOAP request or SOAP response into
     // a local memory buffer.
     public override Stream ChainStream( Stream stream )
            oldStream = stream;
            newStream = new MemoryStream();
            return newStream;

    public override void ProcessMessage(SoapMessage message)
       switch (message.Stage)
            case SoapMessageStage.BeforeDeserialize:
                // before the XML deserialized into object.
            case SoapMessageStage.AfterDeserialize:
            case SoapMessageStage.BeforeSerialize:
            case SoapMessageStage.AfterSerialize:
                throw new Exception("Invalid stage...");

At stage of SoapMessageStage.BeforeDeserialize, You can read the expected data you want from oldstream (e.g. use XmlReader). Then store the expected data somewhere for yourself to use and also you need forward the old stream data to the newstream for web service later stage to use the data, e.g. deserialize XML into objects.

The sample of logging all the traffic for the web service from MSDN